Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
@@ -19,6 +19,7 @@ CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/cuts/include \
-I$(G4BASE)/processes/transportation/include \
-I$(G4BASE)/particles/management/include \
-I$(G4BASE)/particles/bosons/include \
-I$(G4BASE)/particles/leptons/include \
+125 -21
View File
@@ -1,49 +1,153 @@
-------------------------------------------------------------------
# Category emutils History
=========================================================
Geant4 - an Object-Oriented Toolkit for Simulation in HEP
=========================================================
See `CONTRIBUTING.rst` for details of **required** info/format for each entry,
which **must** added in reverse chronological order (newest at the top). It must **not**
be used as a substitute for writing good git commit messages!
Category History file
---------------------
This file should be used by G4 developers and category coordinators
to briefly summarize all major modifications introduced in the code
and keep track of all category-tags.
It DOES NOT substitute the CVS log-message one should put at every
committal in the CVS repository !
----------------------------------------------------------
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
## 2022-06-19 V.Ivanchenko (emutils-V11-00-30)
- G4EmExtraParametersMessenger - fixed typo (problem #2492)
07 April 2022 V.Ivanchenko (emutils-V10-07-40)
## 2022-06-17 V.Ivanchenko (emutils-V11-00-29)
- G4VEnergyLossProcess - fixed trivial Coverity warnings
## 2022-06-07 V.Ivanchenko (emutils-V11-00-28)
- G4VEnergyLossProcess, G4EmDataHandler - improve StorePhysicsTable(..)
method and debug pritouts
## 2022-06-07 V.Ivanchenko (emutils-V11-00-27)
- G4VEnergyLossProcess - moved out common computations to G4EmTableUtil,
use G4EmDataHandler, removed unused headers and methods
## 2022-05-31 V.Ivanchenko (emutils-V11-00-26)
- G4VEmModel - fixed Coverity warning
## 2022-05-28 V.Ivanchenko (emutils-V11-00-25)
- G4EmParametersMessenger - added extra UI command to define model of
fluctuations
## 2022-05-23 V.Ivanchenko (emutils-V11-00-24)
- G4EmTableUtil - added extra methods
- G4VEmModel, G4VEmProcess, G4VEnergyLossProcess,
G4VMultipleScattering, G4LossTableManager - use new utiity methods,
updated sampling of random element in compounds and random
isotopes, code cleanup
- G4EmParameters - added extra parameter: type for of fluctuation model
## 2022-05-20 Z.Li (emutils-V11-00-23)
- G4EmLowEParameters, change default photon database to EPICS2017
## 2022-05-13 V.Ivanchenko (emutils-V11-00-22)
- G4EmUtility - added methods to sample isotopes or element
- G4VEmModel, G4EmCalculator, G4EmConfigurator - use G4EmUtility
## 2022-05-12 V.Ivanchenko (emutils-V11-00-21)
- G4EmUtility - removed precision lost in energy value at
initialisation of integral method
- G4VEmProcess, G4VEnergyLossProcess - for integral method
use master thread cross section type and pointers directly
simplifing initialisation
## 2022-05-11 J.Hahnfeld (emutils-V11-00-20)
- Remove dependency on `G4magneticfield`
## 2022-05-02 J.Hahnfeld (emutils-V11-00-19)
- `G4TransportationWithMsc`: Add possibility of internal stepping
- `G4EmParameters`: Update flag to tristate for enabling it
## 2022-04-29 V.Ivanchenko (emutils-V11-00-18)
- G4EmTableUtil - new utility to perform common computations at
initialisation
- G4VMultipleScattering - use G4EmTableUtil and fix Coverity warnings
- G4EmConfigurator, G4VEnergyLossProcess - fixed Coverity warnings
## 2022-04-27 D.Sawkey (emutils-V11-00-17)
- many files: run clang-tidy. Use default ctors; keywords nullptr, auto, using
## 2022-04-23 V.Ivanchenko (emutils-V11-00-16)
- G4EmConfigurator - implement model per region for G4TransportationWithMsc
- GNUmakefile, source.cmake - updated accordingly
## 2022-04-19 J.Hahnfeld (emutil-V11-00-15)
- Create `G4TransportationWithMsc` process, add flag to `G4EmParameters`
## 2022-04-13 V.Ivanchenko (emutils-V11-00-14)
- G4VEnergyLossProcess, G4VEmProcess - use G4EmUtility to compute cross
section shape parameters
- G4VMultipleScattering - updated arguments for AddEmModel, SetEmModel,
and EmModel methods from G4VEmModel* to G4VMscModel*
- G4EmConfigurator - updated interfaces
## 2022-04-10 V.Ivanchenko (emutils-V11-00-13)
- G4EmUtility - added new static methods to prepare data structures for
integral method using EM tables or using GetCrossSection(..) method
from G4VDiscreteProcess based class, this will allow using it for hadronics
- G4VEnergyLossProcess, G4VEmProcess, G4VMultipleScattering - minor clean-up
## 2022-04-07 V.Ivanchenko (emutils-V11-00-12)
- G4VMultipleScattering - fix #2480 responsible for energy deposition shift of
custom CMS Physics List FTFP_BERT_EMM
01 April 2022 J.Hahnfeld
## 2022-04-01 J.Hahnfeld (emutils-V11-00-11)
- Fix typo in Bremsstrahlung.
24 March 2022: V.Ivanchenko
## 2022-03-29 H.Tran (emutils-V11-00-10)
- G4LowEnergyEmProcessSubType - add fLowEnergyScavenger (66) for DNAScavenger process
## 2022-03-24 V.Ivanchenko (emutils-V11-00-09)
- G4VEnergyLossProcess - fix fluctuation model pointer if an extra
model is added on top of the default list of models
22 January 22: V.Ivanchenko (emutils-V10-07-39)
## 2022-03-17 V.Ivanchenko (emutils-V11-00-08)
- G4EmParametersMessenger - restored UI command "/process/em/integral"
- G4VEmProcess - updated methods to access cross section in run time,
implement new virtual method GetCrossSection, removed unused
methods
- G4EmCalculator - use updated method from G4VEmProcess
- G4EmUtility - a new utility class
## 2022-03-09 V.Ivanchenko (emutils-V11-00-07)
- G4EmCalculator - fixed variable shadowing
## 2022-03-07 V.Ivanchenko (emutils-V11-00-06)
- G4EmModelManager - updated interface to Initialise(.. ) method,
removed obsolete method Update(..)
- G4VEmProcess, G4VEnergyLossProcess, G4VMultipleScattering - use updated
method of G4EmModelManager
## 2022-02-17 V.Ivanchenko (emutils-V11-00-05)
- G4EmParametersMessenger - instantion order of UI directories improved,
directories are created only in the master thread
## 2022-01-22 V.Ivanchenko (emutils-V11-00-04)
- G4EmParametersMessenger - added forgotten UI command to enable polarisation
08 January 22: V.Ivanchenko
## 2022-01-08 V.Ivanchenko (emutils-V11-00-03)
- G4VEmProcess - fixed methods, which implementation based on assumption that
the lambda table defined for full energy range: LambdaPhysicsVector(..),
CrossSEctionPerVolume(...), FindLambdaMax(...). No change is expected for
the default physics configuration, fix mainly affect positron annihilation
processes at high energies.
05 January 22: V.Ivanchenko
## 2022-01-05 V.Ivanchenko (emutils-V11-00-02)
- Complete internal redesign started in 2021, results are identical
- G4EmTableType - added 3d peak energy in the data structure needed for bremsstrahlung
- G4VEnergyLossProcess - fill data structure for bremsstrahlung type of x-section
only in the master thread - do not repeat in each thread; removed ineffective
cache from run time computation of cross section.
- G4VMscModel, G4VEmProcess - move few methods and header files from header to
source in order to reduce dependencies between packages.
17 December 21: I.Hrivnacova
## 2021-12-17 Ivana Hrivnacova (emutils-V11-00-01)
- Added info in setMaxBetaChange command description.
## 2021-12-10 Ben Morgan (emutils-V11-00-00)
- Change to new Markdown History format
---
# History entries prior to 11.0
19 November 21: V.Ivanchenko (emutils-V10-07-38)
- G4EmCalculator - fixed computation of dedx for He3 and alpha
(complete fix of #2440)
@@ -95,7 +95,7 @@ public:
const G4Region* r = nullptr);
inline G4double GetDEDX(G4double kinEnergy, const G4String& part,
const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
G4double GetRangeFromRestricteDEDX(G4double kinEnergy,
const G4ParticleDefinition*,
@@ -104,28 +104,28 @@ public:
inline G4double GetRangeFromRestricteDEDX(G4double kinEnergy,
const G4String& part,
const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
G4double GetCSDARange(G4double kinEnergy, const G4ParticleDefinition*,
const G4Material*,
const G4Region* r = nullptr);
inline G4double GetCSDARange(G4double kinEnergy, const G4String& part,
const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
G4double GetRange(G4double kinEnergy, const G4ParticleDefinition*,
const G4Material*,
const G4Region* r = nullptr);
inline G4double GetRange(G4double kinEnergy, const G4String& part,
const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
G4double GetKinEnergy(G4double range, const G4ParticleDefinition*,
const G4Material*,
const G4Region* r = nullptr);
inline G4double GetKinEnergy(G4double range, const G4String& part,
const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
G4double GetCrossSectionPerVolume(
G4double kinEnergy, const G4ParticleDefinition*,
@@ -133,7 +133,7 @@ public:
const G4Region* r = nullptr);
inline G4double GetCrossSectionPerVolume(
G4double kinEnergy, const G4String& part, const G4String& proc,
const G4String& mat, const G4String& s = "world");
const G4String& mat, const G4String& regname = "world");
G4double GetShellIonisationCrossSectionPerAtom(
const G4String& part, G4int Z,
@@ -145,7 +145,7 @@ public:
const G4Region* r = nullptr);
inline G4double GetMeanFreePath(G4double kinEnergy, const G4String& part,
const G4String& proc, const G4String& mat,
const G4String& s = "world");
const G4String& regname = "world");
void PrintDEDXTable(const G4ParticleDefinition*);
@@ -58,6 +58,7 @@
class G4VEnergyLossProcess;
class G4VEmProcess;
class G4VMultipleScattering;
class G4TransportationWithMsc;
class G4EmConfigurator
{
@@ -93,7 +94,8 @@ public:
G4VEmProcess* p);
void PrepareModels(const G4ParticleDefinition* aParticle,
G4VMultipleScattering* p);
G4VMultipleScattering* p,
G4TransportationWithMsc* trans = nullptr);
void Clear();
@@ -105,8 +107,6 @@ public:
private:
const G4Region* FindRegion(const G4String&);
void SetModelForRegion(G4VEmModel* model,
G4VEmFluctuationModel* fm,
const G4Region* reg,
@@ -67,10 +67,19 @@ public:
~G4EmDataHandler();
// add table
size_t SetTable(G4PhysicsTable*);
// update existing table
void UpdateTable(G4PhysicsTable*, size_t idx);
// assuming that the table is already defined
G4PhysicsTable* MakeTable(size_t idx);
// existing table may be substituted
G4PhysicsTable* MakeTable(G4PhysicsTable*, size_t idx);
// clean existing table
void CleanTable(size_t idx);
G4bool StorePhysicsTable(size_t idx,
@@ -82,7 +91,7 @@ public:
const G4ParticleDefinition* part,
const G4String& fname,
G4bool ascii, G4bool spline);
void SetMasterProcess(const G4VEmProcess*);
const G4VEmProcess* GetMasterProcess(size_t idx) const;
@@ -151,7 +151,7 @@ public:
const G4DataVector* Initialise(const G4ParticleDefinition* part,
const G4ParticleDefinition* secPart,
G4double, G4int verb);
G4int verb);
void FillDEDXVector(G4PhysicsVector*, const G4MaterialCutsCouple*,
G4EmTableType t = fRestricted);
@@ -163,10 +163,8 @@ public:
void AddEmModel(G4int, G4VEmModel*, G4VEmFluctuationModel* fm,
const G4Region* r);
void UpdateEmModel(const G4String& model_name, G4double emin, G4double emax);
// Get model pointer from the model list
G4VEmModel* GetModel(G4int idx, G4bool ver = false);
G4VEmModel* GetModel(G4int idx, G4bool ver = false) const;
// Get model pointer from the model list for a given material cuts couple
// no check on material cuts couple index
@@ -59,15 +59,28 @@
#include "G4DNAModelSubType.hh"
#include "G4EmSaturation.hh"
#include "G4ThreeVector.hh"
#include "G4Threading.hh"
#include <vector>
enum G4eSingleScatteringType
{
fWVI = 0,
fMott,
fDPWA
};
{
fWVI = 0,
fMott,
fDPWA
};
enum class G4TransportationWithMscType
{
fDisabled = 0,
fEnabled,
fMultipleSteps,
};
enum G4EmFluctuationType
{
fDummyFluctuation = 0,
fUniversalFluctuation,
fUrbanFluctuation
};
class G4EmParametersMessenger;
class G4EmExtraParameters;
@@ -152,6 +165,9 @@ public:
void SetUseICRU90Data(G4bool val);
G4bool UseICRU90Data() const;
void SetFluctuationType(G4EmFluctuationType val);
G4EmFluctuationType FluctuationType() const;
void SetDNAFast(G4bool val);
G4bool DNAFast() const;
@@ -279,6 +295,9 @@ public:
void SetWorkerVerbose(G4int val);
G4int WorkerVerbose() const;
void SetTransportationWithMsc(G4TransportationWithMscType val);
G4TransportationWithMscType TransportationWithMsc() const;
void SetMscStepLimitType(G4MscStepLimitType val);
G4MscStepLimitType MscStepLimitType() const;
@@ -425,14 +444,12 @@ private:
G4int workerVerbose;
G4int tripletConv; // 5d model triplet generation type
G4TransportationWithMscType fTransportationWithMsc;
G4MscStepLimitType mscStepLimit;
G4MscStepLimitType mscStepLimitMuHad;
G4NuclearFormfactorType nucFormfactor;
G4eSingleScatteringType fSStype;
#ifdef G4MULTITHREADED
static G4Mutex emParametersMutex;
#endif
G4EmFluctuationType fFluct;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -86,6 +86,7 @@ private:
G4UIdirectory* dnaDirectory;
G4UIcmdWithABool* flucCmd;
G4UIcmdWithABool* intCmd;
G4UIcmdWithABool* rangeCmd;
G4UIcmdWithABool* lpmCmd;
G4UIcmdWithABool* rsCmd;
@@ -132,10 +133,12 @@ private:
G4UIcmdWithAnInteger* ver2Cmd;
G4UIcmdWithAnInteger* tripletCmd;
G4UIcmdWithAString* transWithMscCmd;
G4UIcmdWithAString* mscCmd;
G4UIcmdWithAString* msc1Cmd;
G4UIcmdWithAString* nffCmd;
G4UIcmdWithAString* ssCmd;
G4UIcmdWithAString* fluc1Cmd;
G4UIcommand* dumpCmd;
@@ -51,7 +51,7 @@ enum G4EmSecondaryParticleType
_TripletElectron = 10014,
_Bremsstrahlung = 10020,
// Legacy name for compatibility with Geant4 11.0 and patch01.
// Legacy name for compatibility with Geant4 11.0 and patch01.
_Bremsstruhlung = 10020,
_SplitBremsstrahlung = 10021,
_ComptonGamma = 10022,
@@ -65,6 +65,7 @@ struct G4TwoPeaksXS {
G4double e1deep;
G4double e2peak;
G4double e2deep;
G4double e3peak;
};
#endif
@@ -0,0 +1,163 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Geant4 header G4EmTableUtil
//
// Author V.Ivanchenko 14.03.2022
//
// Utilities used at initialisation of EM physics
//
#ifndef G4EmTableUtil_h
#define G4EmTableUtil_h 1
#include "globals.hh"
#include "G4PhysicsTable.hh"
#include "G4VMultipleScattering.hh"
#include "G4VEmProcess.hh"
#include "G4VEnergyLossProcess.hh"
#include "G4EmModelManager.hh"
#include "G4LossTableBuilder.hh"
#include "G4ParticleDefinition.hh"
#include "G4MscStepLimitType.hh"
#include "G4DataVector.hh"
class G4EmTableUtil
{
public:
static const G4DataVector*
PrepareEmProcess(G4VEmProcess* proc,
const G4ParticleDefinition* part,
const G4ParticleDefinition* secPart,
G4EmModelManager* modelManager,
const G4double& maxKinEnergy,
G4int& secID, G4int& tripletID,
G4int& mainSec, const G4int& verb,
const G4bool& master);
static void BuildEmProcess(G4VEmProcess* proc,
const G4VEmProcess* masterProc,
const G4ParticleDefinition* firstPart,
const G4ParticleDefinition* part,
const G4int nModels, const G4int verb,
const G4bool master, const G4bool isLocked,
const G4bool toBuild, G4bool& baseMat);
static void BuildLambdaTable(G4VEmProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* theLambdaTable,
G4PhysicsTable* theLambdaTablePrim,
const G4double minKinEnergy,
const G4double minKinEnergyPrim,
const G4double maxKinEnergy,
const G4double scale,
const G4int verbose,
const G4bool startFromNull,
const G4bool splineFlag);
static void BuildLambdaTable(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* theLambdaTable,
const G4DataVector* theCuts,
const G4double minKinEnergy,
const G4double maxKinEnergy,
const G4double scale,
const G4int verbose,
const G4bool splineFlag);
static const G4ParticleDefinition* CheckIon(
G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
const G4ParticleDefinition* particle,
const G4int verboseLevel, G4bool& isIon);
static void UpdateModels(G4VEnergyLossProcess* proc,
G4EmModelManager* modelManager,
const G4double maxKinEnergy,
const G4int nModels,
G4int& secID, G4int& biasID,
G4int& mainSecondaries, const G4bool baseMat,
const G4bool isMaster, const G4bool useAGen);
static void BuildLocalElossProcess(G4VEnergyLossProcess* proc,
const G4VEnergyLossProcess* masterProc,
const G4ParticleDefinition* part,
const G4int nModels);
static void BuildDEDXTable(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* table,
const G4double minKinEnergy,
const G4double maxKinEnergy,
const G4int nbins,
const G4int verbose,
const G4EmTableType tType,
const G4bool splineFlag);
static void PrepareMscProcess(G4VMultipleScattering* proc,
const G4ParticleDefinition& part,
G4EmModelManager* modelManager,
G4MscStepLimitType& stepLimit,
G4double& facrange,
G4bool& latDisplacement, G4bool& master,
G4bool& isIon, G4bool& baseMat);
static void BuildMscProcess(G4VMultipleScattering* proc,
const G4VMultipleScattering* masterProc,
const G4ParticleDefinition& part,
const G4ParticleDefinition* firstPart,
G4int nModels, G4bool master);
static G4bool StoreMscTable(G4VMultipleScattering* proc,
const G4ParticleDefinition* part,
const G4String& directory,
const G4int nModels, const G4int verb,
const G4bool ascii);
static G4bool StoreTable(G4VProcess*, const G4ParticleDefinition*,
G4PhysicsTable*, const G4String& dir,
const G4String& tname, G4int verb,
G4bool ascii);
static G4bool RetrieveTable(G4VProcess* ptr,
const G4ParticleDefinition* part,
G4PhysicsTable* aTable,
const G4String& dir, const G4String& tname,
const G4int verb, const G4bool ascii,
const G4bool spline);
};
#endif
@@ -0,0 +1,85 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Geant4 header G4EmUtility
//
// Author V.Ivanchenko 14.03.2022
//
// Utilities used at initialisation of EM physics
//
#ifndef G4EmUtility_h
#define G4EmUtility_h 1
#include <vector>
#include "globals.hh"
#include "G4Region.hh"
#include "G4PhysicsTable.hh"
#include "G4EmTableType.hh"
#include "G4ParticleDefinition.hh"
#include "G4VDiscreteProcess.hh"
#include "G4LossTableBuilder.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4Isotope.hh"
#include "G4DataVector.hh"
#include "G4VEmModel.hh"
class G4EmUtility
{
public:
// find G4Region pointer by name, by default no verbosity
static const G4Region* FindRegion(const G4String& regionName,
const G4int verbose = 0);
// sample random G4Element for the case if cross section is
// proportional to the number of electrons in an atom
static const G4Element* SampleRandomElement(const G4Material*);
// sample random G4Isotope
static const G4Isotope* SampleRandomIsotope(const G4Element*);
// find energy of cross section maximum for all couples
static std::vector<G4double>* FindCrossSectionMax(G4PhysicsTable*);
static std::vector<G4double>*
FindCrossSectionMax(G4VDiscreteProcess*, const G4ParticleDefinition*);
// fill structure describing more than one peak in cross sections
static std::vector<G4TwoPeaksXS*>*
FillPeaksStructure(G4PhysicsTable*, G4LossTableBuilder*);
// model initialisation
static void InitialiseElementSelectors(G4VEmModel*,
const G4ParticleDefinition*,
const G4DataVector& cuts,
const G4double emin,
const G4double emax);
};
#endif
@@ -223,7 +223,7 @@ private:
static G4ThreadLocal G4int let_max_num_warnings;
static G4ThreadLocal G4bool first_loss;
*/
typedef std::map<K,G4EnergyLossTablesHelper,std::less<K> > helper_map;
using helper_map = std::map<K, G4EnergyLossTablesHelper, std::less<K> >;
static helper_map *dict;
static G4EnergyLossTablesHelper GetTables(const G4ParticleDefinition* p);
@@ -56,7 +56,8 @@ enum G4LowEnergyEmProcessSubType
fLowEnergyDoubleIonisation = 62,
fLowEnergyDoubleCap = 63,
fLowEnergyIoniTransfer = 64,
fLowEnergyStaticMol = 65
fLowEnergyStaticMol = 65,
fLowEnergyScavenger = 66
};
#endif
@@ -63,7 +63,7 @@ public:
explicit G4NIELCalculator(G4VEmModel*, G4int verb);
~G4NIELCalculator();
~G4NIELCalculator() = default;
// initialisation before start of run
void Initialise();
@@ -0,0 +1,108 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4TransportationWithMsc
//
// Class Description:
//
// It is a generic process of transportation with multiple scattering included
// in the step limitation and propagation.
//
// Original author: Jonas Hahnfeld, 2022
#ifndef G4TrasportationWithMsc_h
#define G4TrasportationWithMsc_h 1
#include "G4Transportation.hh"
#include <vector>
class G4EmModelManager;
class G4LossTableManager;
class G4ParticleDefinition;
class G4Region;
class G4VMscModel;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4TransportationWithMsc : public G4Transportation
{
public:
enum class ScatteringType
{
MultipleScattering,
};
explicit G4TransportationWithMsc(ScatteringType type, G4int verbosity = 0);
~G4TransportationWithMsc() override;
inline void SetMultipleSteps(G4bool val);
inline G4bool MultipleSteps() const;
void AddMscModel(G4VMscModel* mscModel, G4int order = 0,
const G4Region* region = nullptr);
public:
void PreparePhysicsTable(const G4ParticleDefinition& part) override;
void BuildPhysicsTable(const G4ParticleDefinition& part) override;
void StartTracking(G4Track* track) override;
G4double AlongStepGetPhysicalInteractionLength(
const G4Track& track, G4double previousStepSize,
G4double currentMinimumStep, G4double& proposedSafety,
G4GPILSelection* selection) override;
private:
const ScatteringType fType;
G4bool fMultipleSteps = false;
G4LossTableManager* fEmManager;
G4EmModelManager* fModelManager;
const G4ParticleDefinition* fFirstParticle = nullptr;
G4DynamicParticle* fSubStepDynamicParticle;
G4Track* fSubStepTrack;
G4Step* fSubStep;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4TransportationWithMsc::SetMultipleSteps(G4bool val)
{
fMultipleSteps = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4bool G4TransportationWithMsc::MultipleSteps() const
{
return fMultipleSteps;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -294,7 +294,6 @@ public:
G4double cutEnergy = 0.0,
G4double maxEnergy = DBL_MAX);
// to select atom cross section per volume is recomputed for each element
const G4Element* SelectRandomAtom(const G4Material*,
const G4ParticleDefinition*,
@@ -303,10 +302,12 @@ public:
G4double maxEnergy = DBL_MAX);
// to select atom if cross section is proportional number of electrons
G4int SelectRandomAtomNumber(const G4Material*);
const G4Element* GetCurrentElement(const G4Material* mat = nullptr) const;
G4int SelectRandomAtomNumber(const G4Material*) const;
// select isotope in order to have precise mass of the nucleus
G4int SelectIsotopeNumber(const G4Element*);
const G4Isotope* GetCurrentIsotope(const G4Element* elm = nullptr) const;
G4int SelectIsotopeNumber(const G4Element*) const;
//------------------------------------------------------------------------
// Get/Set methods
@@ -388,10 +389,6 @@ public:
inline void SetCurrentCouple(const G4MaterialCutsCouple*);
inline const G4Element* GetCurrentElement() const;
inline const G4Isotope* GetCurrentIsotope() const;
inline G4bool IsLocked() const;
inline void SetLocked(G4bool);
@@ -415,7 +412,6 @@ private:
G4VEmModel* fTripletModel = nullptr;
const G4MaterialCutsCouple* fCurrentCouple = nullptr;
const G4Element* fCurrentElement = nullptr;
const G4Isotope* fCurrentIsotope = nullptr;
std::vector<G4EmElementSelector*>* elmSelectors = nullptr;
G4LossTableManager* fEmManager;
@@ -497,21 +493,6 @@ inline const G4MaterialCutsCouple* G4VEmModel::CurrentCouple() const
inline void G4VEmModel::SetCurrentElement(const G4Element* elm)
{
fCurrentElement = elm;
fCurrentIsotope = nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4Element* G4VEmModel::GetCurrentElement() const
{
return fCurrentElement;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4Isotope* G4VEmModel::GetCurrentIsotope() const
{
return fCurrentIsotope;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -569,7 +550,7 @@ G4VEmModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition* part,
G4double cutEnergy,
G4double maxEnergy)
{
SetCurrentElement(elm);
fCurrentElement = elm;
return ComputeCrossSectionPerAtom(part,kinEnergy,elm->GetZ(),elm->GetN(),
cutEnergy,maxEnergy);
}
@@ -587,7 +568,6 @@ G4VEmModel::SelectRandomAtom(const G4MaterialCutsCouple* couple,
fCurrentElement = (nSelectors > 0) ?
((*elmSelectors)[couple->GetIndex()])->SelectRandomAtom(kinEnergy) :
SelectRandomAtom(pBaseMaterial,part,kinEnergy,cutEnergy,maxEnergy);
fCurrentIsotope = nullptr;
return fCurrentElement;
}
@@ -605,7 +585,6 @@ G4VEmModel::SelectTargetAtom(const G4MaterialCutsCouple* couple,
fCurrentElement = (nSelectors > 0)
? ((*elmSelectors)[couple->GetIndex()])->SelectRandomAtom(kinEnergy,logKinE)
: SelectRandomAtom(pBaseMaterial,part,kinEnergy,cutEnergy,maxEnergy);
fCurrentIsotope = nullptr;
return fCurrentElement;
}
@@ -95,13 +95,6 @@ protected:
virtual void InitialiseProcess(const G4ParticleDefinition*) = 0;
//------------------------------------------------------------------------
// Method with standard implementation; may be overwritten if needed
//------------------------------------------------------------------------
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition*,
const G4Material*);
//------------------------------------------------------------------------
// Implementation of virtual methods common to all Discrete processes
//------------------------------------------------------------------------
@@ -148,25 +141,21 @@ public:
// Specific methods for Discrete EM post step simulation
//------------------------------------------------------------------------
// It returns the cross section per volume for energy/ material
G4double CrossSectionPerVolume(G4double kineticEnergy,
const G4MaterialCutsCouple* couple,
G4double logKinEnergy = DBL_MAX);
// The main method to access cross section per volume
inline G4double GetLambda(G4double kinEnergy,
const G4MaterialCutsCouple* couple,
G4double logKinEnergy);
// It returns the cross section per volume for energy/material
G4double GetCrossSection(const G4double kinEnergy,
const G4MaterialCutsCouple* couple) override;
// It returns the cross section of the process per atom
G4double ComputeCrossSectionPerAtom(G4double kineticEnergy,
G4double Z, G4double A=0.,
G4double cut=0.0);
G4double MeanFreePath(const G4Track& track);
// Obsolete method to access cross section per volume
G4double GetLambda(G4double kinEnergy, const G4MaterialCutsCouple* couple);
// The main method to access cross section per volume
inline G4double GetLambda(G4double kinEnergy,
const G4MaterialCutsCouple* couple,
G4double logKinEnergy);
inline G4double MeanFreePath(const G4Track& track);
//------------------------------------------------------------------------
// Specific methods to build and access Physics Tables
@@ -184,13 +173,18 @@ public:
// Max kinetic energy for tables
void SetMaxKinEnergy(G4double e);
// for cross section with one peak
void SetEnergyOfCrossSectionMax(std::vector<G4double>*);
// Cross section table pointers
inline G4PhysicsTable* LambdaTable() const;
inline G4PhysicsTable* LambdaTablePrim() const;
inline void SetLambdaTable(G4PhysicsTable*);
inline void SetLambdaTablePrim(G4PhysicsTable*);
// Integral method type and peak positions
inline std::vector<G4double>* EnergyOfCrossSectionMax() const;
inline void SetEnergyOfCrossSectionMax(std::vector<G4double>*);
inline G4CrossSectionType CrossSectionType() const;
inline void SetCrossSectionType(G4CrossSectionType val);
//------------------------------------------------------------------------
// Define and access particle type
//------------------------------------------------------------------------
@@ -198,12 +192,12 @@ public:
inline const G4ParticleDefinition* Particle() const;
inline const G4ParticleDefinition* SecondaryParticle() const;
protected:
//------------------------------------------------------------------------
// Specific methods to set, access, modify models and basic parameters
//------------------------------------------------------------------------
protected:
// Select model in run time
inline G4VEmModel* SelectModel(G4double kinEnergy, size_t);
@@ -230,7 +224,7 @@ public:
inline const G4VEmModel* GetCurrentModel() const;
// Access to models
G4VEmModel* GetModelByIndex(G4int idx = 0, G4bool ver = false) const;
inline G4VEmModel* GetModelByIndex(G4int idx = 0, G4bool ver = false) const;
// Access to the current G4Element
const G4Element* GetCurrentElement() const;
@@ -247,11 +241,7 @@ public:
void ActivateSecondaryBiasing(const G4String& region, G4double factor,
G4double energyLimit);
std::vector<G4double>* FindLambdaMax();
inline void SetEmMasterProcess(const G4VEmProcess*);
inline void SetCrossSectionType(G4CrossSectionType val);
inline void SetBuildTableFlag(G4bool val);
@@ -259,6 +249,11 @@ public:
inline G4bool UseBaseMaterial() const;
void BuildLambdaTable();
void StreamInfo(std::ostream& outFile, const G4ParticleDefinition&,
G4bool rst=false) const;
// hide copy constructor and assignment operator
G4VEmProcess(G4VEmProcess &) = delete;
G4VEmProcess & operator=(const G4VEmProcess &right) = delete;
@@ -286,11 +281,6 @@ protected:
// Single scattering parameters
inline G4double PolarAngleLimit() const;
inline G4CrossSectionType CrossSectionType() const;
inline G4double RecalculateLambda(G4double kinEnergy,
const G4MaterialCutsCouple* couple);
inline G4ParticleChangeForGamma* GetParticleChange();
inline void SetParticle(const G4ParticleDefinition* p);
@@ -311,9 +301,9 @@ protected:
inline void SetSplineFlag(G4bool val);
inline const G4Element* GetTargetElement() const;
const G4Element* GetTargetElement() const;
inline const G4Isotope* GetTargetIsotope() const;
const G4Isotope* GetTargetIsotope() const;
// these two methods assume that vectors are initilized
// and idx is within vector length
@@ -322,13 +312,6 @@ protected:
private:
void Clear();
void BuildLambdaTable();
void StreamInfo(std::ostream& outFile, const G4ParticleDefinition&,
G4bool rst=false) const;
void PrintWarning(G4String tit, G4double val);
void ComputeIntegralLambda(G4double kinEnergy, G4double logKinEnergy);
@@ -391,7 +374,7 @@ private:
G4double maxKinEnergy;
G4double minKinEnergyPrim = DBL_MAX;
G4double lambdaFactor = 0.8;
G4double logLambdaFactor;
G4double invLambdaFactor;
G4double biasFactor = 1.0;
G4double massRatio = 1.0;
G4double fFactor = 1.0;
@@ -456,11 +439,6 @@ private:
// ======== Run time inline methods ================
inline G4bool G4VEmProcess::ApplyCuts() const
{
return applyCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline size_t G4VEmProcess::CurrentMaterialCutsCoupleIndex() const
@@ -615,15 +593,22 @@ G4VEmProcess::GetLambda(G4double kinEnergy, const G4MaterialCutsCouple* couple,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double
G4VEmProcess::RecalculateLambda(G4double e, const G4MaterialCutsCouple* couple)
G4double G4VEmProcess::MeanFreePath(const G4Track& track)
{
CurrentSetup(couple, e);
return fFactor*ComputeCurrentLambda(e);
const G4double kinEnergy = track.GetKineticEnergy();
CurrentSetup(track.GetMaterialCutsCouple(), kinEnergy);
const G4double xs = GetCurrentLambda(kinEnergy,
track.GetDynamicParticle()->GetLogKineticEnergy());
return (0.0 < xs) ? 1.0/xs : DBL_MAX;
}
// ======== Get/Set inline methods used at initialisation ================
inline G4bool G4VEmProcess::ApplyCuts() const
{
return applyCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4int G4VEmProcess::LambdaBinning() const
@@ -668,6 +653,20 @@ inline G4PhysicsTable* G4VEmProcess::LambdaTablePrim() const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEmProcess::SetLambdaTable(G4PhysicsTable* ptr)
{
theLambdaTable = ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEmProcess::SetLambdaTablePrim(G4PhysicsTable* ptr)
{
theLambdaTablePrim = ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline std::vector<G4double>* G4VEmProcess::EnergyOfCrossSectionMax() const
{
return theEnergyOfCrossSectionMax;
@@ -675,6 +674,14 @@ inline std::vector<G4double>* G4VEmProcess::EnergyOfCrossSectionMax() const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void
G4VEmProcess::SetEnergyOfCrossSectionMax(std::vector<G4double>* ptr)
{
theEnergyOfCrossSectionMax = ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4ParticleDefinition* G4VEmProcess::Particle() const
{
return particle;
@@ -746,20 +753,6 @@ inline void G4VEmProcess::SetSplineFlag(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4Element* G4VEmProcess::GetTargetElement() const
{
return currentModel->GetCurrentElement();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4Isotope* G4VEmProcess::GetTargetIsotope() const
{
return currentModel->GetCurrentIsotope();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4int G4VEmProcess::DensityIndex(G4int idx) const
{
return (*theDensityIdx)[idx];
@@ -809,4 +802,11 @@ inline G4VEmModel* G4VEmProcess::EmModel(size_t index) const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4VEmModel* G4VEmProcess::GetModelByIndex(G4int idx, G4bool ver) const
{
return modelManager->GetModel(idx, ver);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -75,6 +75,7 @@ class G4VAtomDeexcitation;
class G4VSubCutProducer;
class G4EmBiasingManager;
class G4LossTableManager;
class G4EmDataHandler;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -99,20 +100,12 @@ protected:
virtual void InitialiseEnergyLossProcess(const G4ParticleDefinition*,
const G4ParticleDefinition*) = 0;
//------------------------------------------------------------------------
// Methods with standard implementation; may be overwritten if needed
//------------------------------------------------------------------------
public:
// used as low energy limit LambdaTable
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition*,
const G4Material*, G4double cut);
//------------------------------------------------------------------------
// Virtual methods implementation common to all EM ContinuousDiscrete
// processes. Further inheritance is not assumed
//------------------------------------------------------------------------
public:
// print documentation in html format
void ProcessDescription(std::ostream& outFile) const override;
@@ -170,19 +163,6 @@ private:
void StreamInfo(std::ostream& out, const G4ParticleDefinition& part,
G4bool rst=false) const;
// store a table
G4bool StoreTable(const G4ParticleDefinition* p,
G4PhysicsTable*, G4bool ascii,
const G4String& directory,
const G4String& tname);
// retrieve a table
G4bool RetrieveTable(const G4ParticleDefinition* p,
G4PhysicsTable*, G4bool ascii,
const G4String& directory,
const G4String& tname,
G4bool mandatory);
//------------------------------------------------------------------------
// Public interface to cross section, mfp and sampling of fluctuations
// These methods are not used in run time
@@ -328,16 +308,17 @@ public:
void SetDEDXTable(G4PhysicsTable* p, G4EmTableType tType);
void SetCSDARangeTable(G4PhysicsTable* pRange);
void SetRangeTableForLoss(G4PhysicsTable* p);
void SetSecondaryRangeTable(G4PhysicsTable* p);
void SetInverseRangeTable(G4PhysicsTable* p);
void SetLambdaTable(G4PhysicsTable* p);
void SetTwoPeaksXS(std::vector<G4TwoPeaksXS*>* p);
void SetTwoPeaksXS(std::vector<G4TwoPeaksXS*>*);
void SetEnergyOfCrossSectionMax(std::vector<G4double>*);
//------------------------------------------------------------------------
// Specific methods to define custom Physics Tables to the process
//------------------------------------------------------------------------
// Binning for dEdx, range, inverse range and labda tables
// Binning for dEdx, range, inverse range and lambda tables
void SetDEDXBinning(G4int nbins);
// Min kinetic energy for tables
@@ -375,11 +356,11 @@ public:
inline G4PhysicsTable* DEDXunRestrictedTable() const;
inline G4PhysicsTable* IonisationTable() const;
inline G4PhysicsTable* CSDARangeTable() const;
inline G4PhysicsTable* SecondaryRangeTable() const;
inline G4PhysicsTable* RangeTableForLoss() const;
inline G4PhysicsTable* InverseRangeTable() const;
inline G4PhysicsTable* LambdaTable() const;
inline std::vector<G4TwoPeaksXS*>* TwoPeaksXS() const;
inline std::vector<G4double>* EnergyOfCrossSectionMax() const;
inline G4bool UseBaseMaterial() const;
@@ -448,18 +429,13 @@ private:
const G4ParticleDefinition* particle = nullptr;
const G4ParticleDefinition* baseParticle = nullptr;
const G4ParticleDefinition* secondaryParticle = nullptr;
const G4ParticleDefinition* theElectron;
const G4ParticleDefinition* thePositron;
const G4ParticleDefinition* theGamma;
const G4ParticleDefinition* theGenericIon = nullptr;
G4EmDataHandler* theData = nullptr;
G4PhysicsTable* theDEDXTable = nullptr;
G4PhysicsTable* theDEDXunRestrictedTable = nullptr;
G4PhysicsTable* theIonisationTable = nullptr;
G4PhysicsTable* theIonisationSubTable = nullptr;
G4PhysicsTable* theRangeTableForLoss = nullptr;
G4PhysicsTable* theCSDARangeTable = nullptr;
G4PhysicsTable* theSecondaryRangeTable = nullptr;
G4PhysicsTable* theInverseRangeTable = nullptr;
G4PhysicsTable* theLambdaTable = nullptr;
@@ -469,6 +445,7 @@ private:
const std::vector<G4double>* theDensityFactor = nullptr;
const G4DataVector* theCuts = nullptr;
std::vector<G4double>* theEnergyOfCrossSectionMax = nullptr;
std::vector<G4TwoPeaksXS*>* fXSpeaks = nullptr;
G4double lowestKinEnergy;
@@ -479,8 +456,8 @@ private:
G4double linLossLimit = 0.01;
G4double dRoverRange = 0.2;
G4double finalRange;
G4double lambdaFactor = 1.0;
G4double logLambdafactor = 0.0;
G4double lambdaFactor = 0.8;
G4double invLambdaFactor;
G4double biasFactor = 1.0;
G4double massRatio = 1.0;
@@ -488,8 +465,6 @@ private:
G4double fFactor = 1.0;
G4double reduceFactor = 1.0;
G4double chargeSqRatio = 1.0;
G4double fLambda = 0.0;
G4double fLambdaEnergy = 0.0;
G4double fRange = 0.0;
G4double fRangeEnergy = 0.0;
@@ -517,7 +492,6 @@ private:
size_t basedCoupleIndex = 0;
size_t coupleIdxRange = 0;
size_t coupleIdxLambda = 0;
size_t idxDEDX = 0;
size_t idxDEDXunRestricted = 0;
size_t idxIonisation = 0;
@@ -528,7 +502,7 @@ private:
size_t idxLambda = 0;
G4GPILSelection aGPILSelection;
G4CrossSectionType fXSType = fEmIncreasing;
G4CrossSectionType fXSType = fEmOnePeak;
G4bool lossFluctuationFlag = true;
G4bool rndmStepFlag = false;
@@ -548,8 +522,7 @@ private:
G4bool actMaxKinEnergy = false;
std::vector<G4DynamicParticle*> secParticles;
std::vector<G4Track*> scTracks;
std::vector<G4Track*> scTracks;
};
// ======== Run time inline methods ================
@@ -581,7 +554,7 @@ inline void
G4VEnergyLossProcess::DefineMaterial(const G4MaterialCutsCouple* couple)
{
if(couple != currentCouple) {
currentCouple = couple;
currentCouple = couple;
currentMaterial = couple->GetMaterial();
basedCoupleIndex = currentCoupleIndex = couple->GetIndex();
fFactor = chargeSqRatio*biasFactor;
@@ -712,12 +685,7 @@ inline G4double G4VEnergyLossProcess::ScaledKinEnergyForLoss(G4double r)
inline G4double G4VEnergyLossProcess::GetLambdaForScaledEnergy(G4double e)
{
if(currentCoupleIndex != coupleIdxLambda || fLambdaEnergy != e) {
coupleIdxLambda = currentCoupleIndex;
fLambdaEnergy = e;
fLambda = fFactor*((*theLambdaTable)[basedCoupleIndex])->Value(e, idxLambda);
}
return fLambda;
return fFactor*((*theLambdaTable)[basedCoupleIndex])->Value(e, idxLambda);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -725,13 +693,7 @@ inline G4double G4VEnergyLossProcess::GetLambdaForScaledEnergy(G4double e)
inline G4double
G4VEnergyLossProcess::GetLambdaForScaledEnergy(G4double e, G4double loge)
{
if(currentCoupleIndex != coupleIdxLambda || fLambdaEnergy != e) {
coupleIdxLambda = currentCoupleIndex;
fLambdaEnergy = e;
fLambda = fFactor*
((*theLambdaTable)[basedCoupleIndex])->LogVectorValue(e, loge);
}
return fLambda;
return fFactor*((*theLambdaTable)[basedCoupleIndex])->LogVectorValue(e, loge);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -981,13 +943,6 @@ inline G4PhysicsTable* G4VEnergyLossProcess::CSDARangeTable() const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4PhysicsTable* G4VEnergyLossProcess::SecondaryRangeTable() const
{
return theSecondaryRangeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4PhysicsTable* G4VEnergyLossProcess::RangeTableForLoss() const
{
return theRangeTableForLoss;
@@ -1016,6 +971,14 @@ inline G4bool G4VEnergyLossProcess::UseBaseMaterial() const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline std::vector<G4double>*
G4VEnergyLossProcess::EnergyOfCrossSectionMax() const
{
return theEnergyOfCrossSectionMax;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline std::vector<G4TwoPeaksXS*>* G4VEnergyLossProcess::TwoPeaksXS() const
{
return fXSpeaks;
@@ -1032,8 +995,7 @@ inline size_t G4VEnergyLossProcess::NumberOfModels() const
inline G4VEmModel* G4VEnergyLossProcess::EmModel(size_t index) const
{
return (nullptr != emModels && index < emModels->size())
? (*emModels)[index] : nullptr;
return (index < emModels->size()) ? (*emModels)[index] : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -328,6 +328,8 @@ G4VMscModel::GetTransportMeanFreePath(const G4ParticleDefinition* part,
return (x > 0.0) ? 1.0/x : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double
G4VMscModel::GetTransportMeanFreePath(const G4ParticleDefinition* part,
G4double ekin, G4double logekin)
@@ -98,10 +98,14 @@ public:
void ProcessDescription(std::ostream& outFile) const override;
protected:
virtual void InitialiseProcess(const G4ParticleDefinition*) = 0;
// Print out of generic class parameters
void StreamInfo(std::ostream& outFile, const G4ParticleDefinition&,
G4bool rst = false) const;
protected:
virtual void StreamProcessInfo(std::ostream&) const {};
public:
@@ -178,7 +182,7 @@ public:
// Add model for region, smaller value of order defines which
// model will be selected for a given energy interval
void AddEmModel(G4int order, G4VEmModel*, const G4Region* region = nullptr);
void AddEmModel(G4int order, G4VMscModel*, const G4Region* region = nullptr);
// Assign a model to a process local list, to enable the list in run time
// the derived process should execute AddEmModel(..) for all such models
@@ -190,14 +194,12 @@ public:
// Access to run time models
inline G4int NumberOfModels() const;
inline G4VMscModel* GetModelByIndex(G4int idx = 0, G4bool ver = false) const;
inline G4VMscModel* GetModelByIndex(G4int idx, G4bool ver = false) const;
//------------------------------------------------------------------------
// Get/Set parameters for simulation of multiple scattering
//------------------------------------------------------------------------
void SetIonisation(G4VEnergyLossProcess*);
inline G4bool LateralDisplasmentFlag() const;
inline G4double Skin() const;
@@ -237,10 +239,6 @@ protected:
private:
// Print out of generic class parameters
void StreamInfo(std::ostream& outFile, const G4ParticleDefinition&,
G4bool rst = false) const;
// ======== Parameters of the class fixed at construction =========
G4EmModelManager* modelManager;
@@ -337,7 +335,7 @@ inline G4double G4VMultipleScattering::PolarAngleLimit() const
inline G4MscStepLimitType G4VMultipleScattering::StepLimitType() const
{
return theParameters->MscStepLimitType();
return stepLimit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -387,6 +385,7 @@ inline G4int G4VMultipleScattering::NumberOfModels() const
inline G4VMscModel*
G4VMultipleScattering::GetModelByIndex(G4int idx, G4bool ver) const
{
// static cast is possible inside this class
return static_cast<G4VMscModel*>(modelManager->GetModel(idx, ver));
}
@@ -60,7 +60,7 @@ public:
explicit G4VSubCutProducer(const G4String& name) : fName(name) {};
virtual ~G4VSubCutProducer() {};
virtual ~G4VSubCutProducer() = default;
// Sample direction in global coordinate system,
// this means for zero scattering angle this direction is the same
@@ -27,6 +27,8 @@ geant4_add_module(G4emutils
G4EmSaturation.hh
G4EmSecondaryParticleType.hh
G4EmTableType.hh
G4EmTableUtil.hh
G4EmUtility.hh
G4EnergyLossTables.hh
G4LossTableBuilder.hh
G4LossTableManager.hh
@@ -36,6 +38,7 @@ geant4_add_module(G4emutils
G4NuclearFormfactorType.hh
G4OpticalParameters.hh
G4OpticalParametersMessenger.hh
G4TransportationWithMsc.hh
G4VAtomDeexcitation.hh
G4VEmAngularDistribution.hh
G4VEmFluctuationModel.hh
@@ -65,12 +68,15 @@ geant4_add_module(G4emutils
G4EmParameters.cc
G4EmParametersMessenger.cc
G4EmSaturation.cc
G4EmTableUtil.cc
G4EmUtility.cc
G4EnergyLossTables.cc
G4LossTableBuilder.cc
G4LossTableManager.cc
G4NIELCalculator.cc
G4OpticalParameters.cc
G4OpticalParametersMessenger.cc
G4TransportationWithMsc.cc
G4VAtomDeexcitation.cc
G4VEmAngularDistribution.cc
G4VEmFluctuationModel.cc
@@ -93,6 +99,7 @@ geant4_module_link_libraries(G4emutils
G4partman
G4procman
G4track
G4transportation
PRIVATE
G4baryons
G4bosons
@@ -45,8 +45,7 @@
G4AngleDirect::G4AngleDirect() : G4VEmAngularDistribution("AngleDirect")
{}
G4AngleDirect::~G4AngleDirect()
{}
G4AngleDirect::~G4AngleDirect() = default;
G4ThreeVector& G4AngleDirect::SampleDirection(const G4DynamicParticle* dp,
G4double, G4int,
@@ -57,8 +57,7 @@ G4DummyModel::G4DummyModel(const G4String& nam)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DummyModel::~G4DummyModel()
{}
G4DummyModel::~G4DummyModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -66,8 +66,7 @@ G4ElectronIonPair::G4ElectronIonPair(G4int verb)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ElectronIonPair::~G4ElectronIonPair()
{}
G4ElectronIonPair::~G4ElectronIonPair() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -106,7 +105,7 @@ G4double G4ElectronIonPair::MeanNumberOfIonsAlongStep(
std::vector<G4ThreeVector>*
G4ElectronIonPair::SampleIonsAlongStep(const G4Step* step)
{
std::vector<G4ThreeVector>* v = 0;
std::vector<G4ThreeVector>* v = nullptr;
G4int nion = SampleNumberOfIonsAlongStep(step);
@@ -74,8 +74,7 @@ G4EmBiasingManager::G4EmBiasingManager()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmBiasingManager::~G4EmBiasingManager()
{}
G4EmBiasingManager::~G4EmBiasingManager() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -415,7 +414,7 @@ G4EmBiasingManager::ApplySecondaryBiasing(std::vector<G4Track*>& track,
if(G4UniformRand()*weight > 1.0) {
const G4Track* t = track[k];
delete t;
track[k] = 0;
track[k] = nullptr;
}
}
}
@@ -444,7 +443,7 @@ G4EmBiasingManager::ApplyRangeCut(std::vector<G4DynamicParticle*>& vd,
if(eIonisation->GetRange(e, track.GetMaterialCutsCouple()) < safety) {
eloss += e;
delete dp;
vd[k] = 0;
vd[k] = nullptr;
}
}
}
@@ -589,9 +588,9 @@ G4EmBiasingManager::ApplyDirectionalSplitting(
foundPrimaryParticle = true;
primaryWeight = weight;
} else {
G4DynamicParticle* dp = new G4DynamicParticle(theGamma,
partChange->GetProposedMomentumDirection(),
partChange->GetProposedKineticEnergy());
auto dp = new G4DynamicParticle(theGamma,
partChange->GetProposedMomentumDirection(),
partChange->GetProposedKineticEnergy());
vd.push_back(dp);
fDirectionalSplittingWeights.push_back(1.);
}
@@ -602,9 +601,9 @@ G4EmBiasingManager::ApplyDirectionalSplitting(
primaryMomdir = momdir;
primaryWeight = 1.;
} else {
G4DynamicParticle* dp = new G4DynamicParticle(theGamma,
partChange->GetProposedMomentumDirection(),
partChange->GetProposedKineticEnergy());
auto dp = new G4DynamicParticle(theGamma,
partChange->GetProposedMomentumDirection(),
partChange->GetProposedKineticEnergy());
vd.push_back(dp);
fDirectionalSplittingWeights.push_back(1./weight);
}
@@ -69,6 +69,7 @@
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4EmUtility.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -247,11 +248,11 @@ G4double G4EmCalculator::GetCrossSectionPerVolume(G4double kinEnergy,
G4VEmProcess* emproc = FindDiscreteProcess(p, processName);
if(emproc) {
res = emproc->CrossSectionPerVolume(kinEnergy, couple);
res = emproc->GetCrossSection(kinEnergy, couple);
} else if(currentLambda) {
// special tables are built for Msc models (procType is set in FindLambdaTable
if(procType==2) {
G4VMscModel* mscM = static_cast<G4VMscModel*>(currentModel);
auto mscM = static_cast<G4VMscModel*>(currentModel);
mscM->SetCurrentCouple(couple);
G4double tr1Mfp = mscM->GetTransportMeanFreePath(p, kinEnergy);
if (tr1Mfp<DBL_MAX) {
@@ -367,7 +368,8 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
// Special case of ICRU'73 model
const G4String& mname = currentModel->GetName();
if(mname == "ParamICRU73" || mname == "LinhardSorensen" || mname == "Atima") {
if(mname == "ParamICRU73" || mname == "LinhardSorensen" ||
mname == "Atima") {
res = currentModel->ComputeDEDXPerVolume(mat, p, kinEnergy, cut);
if(verbose > 1) {
G4cout << mname << " ion E(MeV)= " << kinEnergy << " ";
@@ -388,7 +390,9 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
}
} else {
res = currentModel->ComputeDEDXPerVolume(mat, p, kinEnergy, cut);
if(verbose > 1) { G4cout << " no basePart E(MeV)= " << kinEnergy << " "; }
if(verbose > 1) {
G4cout << " no basePart E(MeV)= " << kinEnergy << " ";
}
}
if(verbose > 1) {
G4cout << currentModel->GetName() << ": DEDX(MeV/mm)= " << res*mm/MeV
@@ -404,10 +408,10 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
G4double res0 = 0.0;
G4double res1 = 0.0;
if(baseParticle) {
res1 = currentModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut)
* chargeSquare;
res0 = loweModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut)
* chargeSquare;
res1 = chargeSquare*
currentModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut);
res0 = chargeSquare*
loweModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut);
} else {
res1 = currentModel->ComputeDEDXPerVolume(mat, p, eth, cut);
res0 = loweModel->ComputeDEDXPerVolume(mat, p, eth, cut);
@@ -430,7 +434,7 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
// low energy correction for ions
if(isIon) {
G4double length = CLHEP::nm;
const G4Region* r = 0;
const G4Region* r = nullptr;
const G4MaterialCutsCouple* couple = FindCouple(mat, r);
G4double eloss = res*length;
dynParticle->SetKineticEnergy(kinEnergy);
@@ -440,8 +444,8 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
if(verbose > 1) {
G4cout << "After Corrections: DEDX(MeV/mm)= " << res*mm/MeV
<< " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
<< G4endl;
<< " DEDX(MeV*cm^2/g)= "
<< res*gram/(MeV*cm2*mat->GetDensity()) << G4endl;
}
}
}
@@ -482,10 +486,10 @@ G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy,
for(G4int i=0; i<n; ++i) {
if(vel[i]) {
G4VProcess* p = reinterpret_cast<G4VProcess*>(vel[i]);
auto p = reinterpret_cast<G4VProcess*>(vel[i]);
if(ActiveForParticle(part, p)) {
//G4cout << "idx= " << i << " " << (vel[i])->GetProcessName()
// << " " << (vel[i])->Particle()->GetParticleName() << G4endl;
// << " " << (vel[i])->Particle()->GetParticleName() << G4endl;
dedx += ComputeDEDX(kinEnergy,part,(vel[i])->GetProcessName(),mat,cut);
}
}
@@ -496,10 +500,11 @@ G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCalculator::ComputeDEDXForCutInRange(G4double kinEnergy,
const G4ParticleDefinition* part,
const G4Material* mat,
G4double rangecut)
G4double
G4EmCalculator::ComputeDEDXForCutInRange(G4double kinEnergy,
const G4ParticleDefinition* part,
const G4Material* mat,
G4double rangecut)
{
SetupMaterial(mat);
G4double dedx = 0.0;
@@ -512,9 +517,12 @@ G4double G4EmCalculator::ComputeDEDXForCutInRange(G4double kinEnergy,
if(mat != cutMaterial) {
cutMaterial = mat;
cutenergy[0] = ComputeEnergyCutFromRangeCut(rangecut, G4Gamma::Gamma(), mat);
cutenergy[1] = ComputeEnergyCutFromRangeCut(rangecut, G4Electron::Electron(), mat);
cutenergy[2] = ComputeEnergyCutFromRangeCut(rangecut, G4Positron::Positron(), mat);
cutenergy[0] =
ComputeEnergyCutFromRangeCut(rangecut, G4Gamma::Gamma(), mat);
cutenergy[1] =
ComputeEnergyCutFromRangeCut(rangecut, G4Electron::Electron(), mat);
cutenergy[2] =
ComputeEnergyCutFromRangeCut(rangecut, G4Positron::Positron(), mat);
}
//G4cout << "ComputeElectronicDEDX for " << part->GetParticleName()
@@ -522,10 +530,10 @@ G4double G4EmCalculator::ComputeDEDXForCutInRange(G4double kinEnergy,
for(G4int i=0; i<n; ++i) {
if(vel[i]) {
G4VProcess* p = reinterpret_cast<G4VProcess*>(vel[i]);
auto p = reinterpret_cast<G4VProcess*>(vel[i]);
if(ActiveForParticle(part, p)) {
//G4cout << "idx= " << i << " " << (vel[i])->GetProcessName()
// << " " << (vel[i])->Particle()->GetParticleName() << G4endl;
// << " " << (vel[i])->Particle()->GetParticleName() << G4endl;
const G4ParticleDefinition* sec = (vel[i])->SecondaryParticle();
G4int idx = 0;
if(sec == G4Electron::Electron()) { idx = 1; }
@@ -601,7 +609,8 @@ G4double G4EmCalculator::ComputeCrossSectionPerVolume(
res = currentModel->CrossSectionPerVolume(mat, p, e, aCut, e);
}
if(verbose>0) {
G4cout << "G4EmCalculator::ComputeXSPerVolume: E(MeV)= " << kinEnergy/MeV
G4cout << "G4EmCalculator::ComputeXSPerVolume: E(MeV)= "
<< kinEnergy/MeV
<< " cross(cm-1)= " << res*cm
<< " cut(keV)= " << aCut/keV
<< " " << p->GetParticleName()
@@ -615,12 +624,12 @@ G4double G4EmCalculator::ComputeCrossSectionPerVolume(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCalculator::ComputeCrossSectionPerAtom(
G4double kinEnergy,
const G4ParticleDefinition* p,
const G4String& processName,
G4double Z, G4double A,
G4double cut)
G4double
G4EmCalculator::ComputeCrossSectionPerAtom(G4double kinEnergy,
const G4ParticleDefinition* p,
const G4String& processName,
G4double Z, G4double A,
G4double cut)
{
G4double res = 0.0;
if(UpdateParticle(p, kinEnergy)) {
@@ -653,11 +662,12 @@ G4double G4EmCalculator::ComputeCrossSectionPerAtom(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCalculator::ComputeCrossSectionPerShell(G4double kinEnergy,
const G4ParticleDefinition* p,
const G4String& processName,
G4int Z, G4int shellIdx,
G4double cut)
G4double
G4EmCalculator::ComputeCrossSectionPerShell(G4double kinEnergy,
const G4ParticleDefinition* p,
const G4String& processName,
G4int Z, G4int shellIdx,
G4double cut)
{
G4double res = 0.0;
if(UpdateParticle(p, kinEnergy)) {
@@ -668,8 +678,9 @@ G4double G4EmCalculator::ComputeCrossSectionPerShell(G4double kinEnergy,
if(baseParticle) {
e *= kinEnergy*massRatio;
currentModel->InitialiseForElement(baseParticle, Z);
res = currentModel->ComputeCrossSectionPerShell(baseParticle, Z, shellIdx,
e, aCut) * chargeSquare;
res =
currentModel->ComputeCrossSectionPerShell(baseParticle, Z, shellIdx,
e, aCut) * chargeSquare;
} else {
currentModel->InitialiseForElement(p, Z);
res = currentModel->ComputeCrossSectionPerAtom(p, Z, shellIdx, e, aCut);
@@ -728,10 +739,11 @@ G4double G4EmCalculator::ComputeMeanFreePath(G4double kinEnergy,
const G4ParticleDefinition* p,
const G4String& processName,
const G4Material* mat,
G4double cut)
G4double cut)
{
G4double mfp = DBL_MAX;
G4double x = ComputeCrossSectionPerVolume(kinEnergy, p, processName, mat, cut);
G4double x =
ComputeCrossSectionPerVolume(kinEnergy, p, processName, mat, cut);
if(x > 0.0) { mfp = 1.0/x; }
if(verbose>1) {
G4cout << "E(MeV)= " << kinEnergy/MeV
@@ -765,7 +777,7 @@ G4bool G4EmCalculator::UpdateParticle(const G4ParticleDefinition* p,
currentParticle = p;
dynParticle->SetDefinition(const_cast<G4ParticleDefinition*>(p));
dynParticle->SetKineticEnergy(kinEnergy);
baseParticle = 0;
baseParticle = nullptr;
currentParticleName = p->GetParticleName();
massRatio = 1.0;
mass = p->GetPDGMass();
@@ -825,7 +837,7 @@ G4bool G4EmCalculator::UpdateParticle(const G4ParticleDefinition* p,
const G4ParticleDefinition* G4EmCalculator::FindParticle(const G4String& name)
{
const G4ParticleDefinition* p = 0;
const G4ParticleDefinition* p = nullptr;
if(name != currentParticleName) {
p = G4ParticleTable::GetParticleTable()->FindParticle(name);
if(!p) {
@@ -864,13 +876,7 @@ const G4Material* G4EmCalculator::FindMaterial(const G4String& name)
const G4Region* G4EmCalculator::FindRegion(const G4String& reg)
{
const G4Region* r = 0;
if(reg != "" && reg != "world") {
r = G4RegionStore::GetInstance()->GetRegion(reg);
} else {
r = G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld");
}
return r;
return G4EmUtility::FindRegion(reg);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1136,13 +1142,13 @@ G4VEnergyLossProcess*
G4EmCalculator::FindEnLossProcess(const G4ParticleDefinition* part,
const G4String& processName)
{
G4VEnergyLossProcess* proc = 0;
G4VEnergyLossProcess* proc = nullptr;
const std::vector<G4VEnergyLossProcess*> v =
manager->GetEnergyLossProcessVector();
G4int n = v.size();
for(G4int i=0; i<n; ++i) {
if((v[i])->GetProcessName() == processName) {
G4VProcess* p = reinterpret_cast<G4VProcess*>(v[i]);
auto p = reinterpret_cast<G4VProcess*>(v[i]);
if(ActiveForParticle(part, p)) {
proc = v[i];
break;
@@ -1167,7 +1173,7 @@ G4EmCalculator::FindDiscreteProcess(const G4ParticleDefinition* part,
proc = v[i]->GetEmProcess(processName);
break;
} else if(pName == processName) {
G4VProcess* p = reinterpret_cast<G4VProcess*>(v[i]);
auto p = reinterpret_cast<G4VProcess*>(v[i]);
if(ActiveForParticle(part, p)) {
proc = v[i];
break;
@@ -1183,13 +1189,13 @@ G4VMultipleScattering*
G4EmCalculator::FindMscProcess(const G4ParticleDefinition* part,
const G4String& processName)
{
G4VMultipleScattering* proc = 0;
G4VMultipleScattering* proc = nullptr;
const std::vector<G4VMultipleScattering*> v =
manager->GetMultipleScatteringVector();
G4int n = v.size();
for(G4int i=0; i<n; ++i) {
if((v[i])->GetProcessName() == processName) {
G4VProcess* p = reinterpret_cast<G4VProcess*>(v[i]);
auto p = reinterpret_cast<G4VProcess*>(v[i]);
if(ActiveForParticle(part, p)) {
proc = v[i];
break;
@@ -1204,7 +1210,7 @@ G4EmCalculator::FindMscProcess(const G4ParticleDefinition* part,
G4VProcess* G4EmCalculator::FindProcess(const G4ParticleDefinition* part,
const G4String& processName)
{
G4VProcess* proc = 0;
G4VProcess* proc = nullptr;
const G4ProcessManager* procman = part->GetProcessManager();
G4ProcessVector* pv = procman->GetProcessList();
G4int nproc = pv->size();
@@ -1243,7 +1249,7 @@ void G4EmCalculator::SetupMaterial(const G4Material* mat)
currentMaterial = mat;
currentMaterialName = mat->GetName();
} else {
currentMaterial = 0;
currentMaterial = nullptr;
currentMaterialName = "";
}
}
@@ -46,6 +46,7 @@
//
#include "G4EmConfigurator.hh"
#include "G4EmUtility.hh"
#include "G4SystemOfUnits.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
@@ -58,6 +59,7 @@
#include "G4VEnergyLossProcess.hh"
#include "G4VEmProcess.hh"
#include "G4VMultipleScattering.hh"
#include "G4TransportationWithMsc.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -68,8 +70,7 @@ G4EmConfigurator::G4EmConfigurator(G4int val):verbose(val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmConfigurator::~G4EmConfigurator()
{}
G4EmConfigurator::~G4EmConfigurator() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -110,13 +111,13 @@ void G4EmConfigurator::SetExtraEmModel(const G4String& particleName,
void G4EmConfigurator::AddModels()
{
size_t n = models.size();
if(0 < verbose) {
if(1 < verbose) {
G4cout << "### G4EmConfigurator::AddModels n= " << n << G4endl;
}
if(n > 0) {
for(size_t i=0; i<n; ++i) {
if(nullptr != models[i]) {
const G4Region* reg = FindRegion(regions[i]);
const G4Region* reg = G4EmUtility::FindRegion(regions[i]);
if(nullptr != reg) {
--index;
SetModelForRegion(models[i],flucModels[i],reg,
@@ -178,36 +179,67 @@ void G4EmConfigurator::SetModelForRegion(G4VEmModel* mod,
break;
}
}
G4bool isCombinedMscTrans = false;
G4TransportationWithMsc* trans = nullptr;
if(nullptr == proc) {
G4cout << "### G4EmConfigurator WARNING: fails to find a process <"
<< processName << "> for " << particleName << G4endl;
return;
}
if(processName == "msc") {
for(G4int i=0; i<np; ++i) {
trans = dynamic_cast<G4TransportationWithMsc*>((*plist)[i]);
if(nullptr != trans) {
G4cout << "G4TransportationWithMsc is found out!" << G4endl;
isCombinedMscTrans = true;
proc = trans;
break;
}
}
}
if(nullptr == proc) {
if(0 < verbose) {
G4cout << "### G4EmConfigurator WARNING: fails to find a process <"
<< processName << "> for " << particleName << G4endl;
}
return;
}
}
if(!UpdateModelEnergyRange(mod, emin, emax)) { return; }
// classify process
G4int ii = proc->GetProcessSubType();
if(10 == ii) {
G4VMultipleScattering* p = static_cast<G4VMultipleScattering*>(proc);
p->AddEmModel(index,mod,reg);
auto msc = dynamic_cast<G4VMscModel*>(mod);
if(isCombinedMscTrans && nullptr != msc) {
trans->AddMscModel(msc, index, reg);
if(1 < verbose) {
G4cout << "### Added msc model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
<< particleName << " and " << proc->GetProcessName()
<< G4endl;
}
} else if(10 == ii && nullptr != msc) {
auto p = dynamic_cast<G4VMultipleScattering*>(proc);
if(nullptr != p) {
p->AddEmModel(index, msc, reg);
if(1 < verbose) {
G4cout << "### Added msc model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
}
}
} else if(2 <= ii && 4 >= ii) {
G4VEnergyLossProcess* p = static_cast<G4VEnergyLossProcess*>(proc);
p->AddEmModel(index,mod,fm,reg);
if(1 < verbose) {
G4cout << "### Added eloss model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
}
auto p = dynamic_cast<G4VEnergyLossProcess*>(proc);
if(nullptr != p) {
p->AddEmModel(index,mod,fm,reg);
if(1 < verbose) {
G4cout << "### Added eloss model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
}
}
} else {
G4VEmProcess* p = static_cast<G4VEmProcess*>(proc);
p->AddEmModel(index,mod,reg);
if(1 < verbose) {
G4cout << "### Added em model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
}
auto p = dynamic_cast<G4VEmProcess*>(proc);
if(nullptr != p) {
p->AddEmModel(index,mod,reg);
if(1 < verbose) {
G4cout << "### Added em model order= " << index << " for "
<< particleName << " and " << processName << G4endl;
}
}
}
return;
}
@@ -235,7 +267,7 @@ G4EmConfigurator::PrepareModels(const G4ParticleDefinition* aParticle,
if((particleName == particles[i]) ||
(particles[i] == "all") ||
(particles[i] == "charged" && aParticle->GetPDGCharge() != 0.0)) {
const G4Region* reg = FindRegion(regions[i]);
const G4Region* reg = G4EmUtility::FindRegion(regions[i]);
//G4cout << "Region " << reg << G4endl;
if(nullptr != reg) {
--index;
@@ -280,7 +312,7 @@ G4EmConfigurator::PrepareModels(const G4ParticleDefinition* aParticle,
if((particleName == particles[i]) ||
(particles[i] == "all") ||
(particles[i] == "charged" && aParticle->GetPDGCharge() != 0.0)) {
const G4Region* reg = FindRegion(regions[i]);
const G4Region* reg = G4EmUtility::FindRegion(regions[i]);
//G4cout << "Region " << reg << G4endl;
if(nullptr != reg) {
--index;
@@ -305,7 +337,8 @@ G4EmConfigurator::PrepareModels(const G4ParticleDefinition* aParticle,
void
G4EmConfigurator::PrepareModels(const G4ParticleDefinition* aParticle,
G4VMultipleScattering* p)
G4VMultipleScattering* p,
G4TransportationWithMsc* trans)
{
size_t n = particles.size();
if(1 < verbose) {
@@ -314,22 +347,26 @@ G4EmConfigurator::PrepareModels(const G4ParticleDefinition* aParticle,
}
if(n > 0) {
G4String particleName = aParticle->GetParticleName();
G4String processName = p->GetProcessName();
G4String particleName = aParticle->GetParticleName();
G4String processName = (nullptr == p) ? "msc" : p->GetProcessName();
for(size_t i=0; i<n; ++i) {
if(processName == processes[i]) {
if((particleName == particles[i]) ||
(particles[i] == "all") ||
(particles[i] == "charged" && aParticle->GetPDGCharge() != 0.0)) {
const G4Region* reg = FindRegion(regions[i]);
if(nullptr != reg) {
--index;
G4VEmModel* mod = models[i];
if((particleName == particles[i]) ||
(particles[i] == "all") ||
(particles[i] == "charged" && aParticle->GetPDGCharge() != 0.0)) {
const G4Region* reg = G4EmUtility::FindRegion(regions[i]);
if(nullptr != reg) {
--index;
auto mod = dynamic_cast<G4VMscModel*>(models[i]);
if(nullptr != mod) {
if(UpdateModelEnergyRange(mod, lowEnergy[i], highEnergy[i])) {
p->AddEmModel(index,mod,reg);
if(UpdateModelEnergyRange(mod, lowEnergy[i], highEnergy[i])) {
if(nullptr != p) {
p->AddEmModel(index,mod,reg);
} else {
trans->AddMscModel(mod,index,reg);
}
//G4cout << "### Added msc model order= " << index << " for "
// << particleName << " and " << processName << G4endl;
// << particleName << " and " << processName << G4endl;
}
}
}
@@ -354,28 +391,6 @@ void G4EmConfigurator::Clear()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const G4Region* G4EmConfigurator::FindRegion(const G4String& regionName)
{
// search for region
const G4Region* reg = nullptr;
G4RegionStore* regStore = G4RegionStore::GetInstance();
G4String r = regionName;
if(r == "" || r == "world" || r == "World") {
r = "DefaultRegionForTheWorld";
}
reg = regStore->GetRegion(r, true);
if(nullptr == reg) {
G4cout << "### G4EmConfigurator WARNING: fails to find a region <"
<< r << G4endl;
} else if(verbose > 1) {
G4cout << "### G4EmConfigurator finds out G4Region <" << r << ">"
<< G4endl;
}
return reg;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4EmConfigurator::UpdateModelEnergyRange(G4VEmModel* mod,
G4double emin, G4double emax)
{
@@ -852,8 +852,7 @@ void G4EmCorrections::BuildCorrectionVector()
<< ion->GetParticleName() << G4endl;
}
G4PhysicsLogVector* vv =
new G4PhysicsLogVector(eCorrMin,eCorrMax,nbinCorr,false);
auto vv = new G4PhysicsLogVector(eCorrMin,eCorrMax,nbinCorr,false);
const G4double eth0 = v->Energy(0);
const G4double escal = eth/massFactor;
G4double qe =
@@ -904,8 +903,7 @@ void G4EmCorrections::InitialiseForNewRun()
ncouples = tb->GetTableSize();
if(currmat.size() != ncouples) {
currmat.resize(ncouples);
for(std::map< G4int, std::vector<G4double> >::iterator it =
thcorr.begin(); it != thcorr.end(); ++it){
for(auto it = thcorr.begin(); it != thcorr.end(); ++it){
(it->second).clear();
}
thcorr.clear();
@@ -58,9 +58,12 @@ G4EmDataHandler::G4EmDataHandler(size_t n) : tLength(n)
G4EmDataHandler::~G4EmDataHandler()
{
//std::cout << "G4EmDataHandler::~G4EmDataHandler "
// << tLength << " " << this << std::endl;
for(size_t i=0; i<tLength; ++i) { CleanTable(i); }
for(size_t i=0; i<tLength; ++i) {
for(size_t j = i+1; j<tLength; ++j) {
if(data[j] == data[i]) { data[j] = nullptr; }
}
CleanTable(i);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -74,27 +77,56 @@ size_t G4EmDataHandler::SetTable(G4PhysicsTable* ptr)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmDataHandler::UpdateTable(G4PhysicsTable* ptr, size_t idx)
{
// update table pointer but not delete previous
if(idx < tLength) {
if(ptr != data[idx]) { data[idx] = ptr; }
} else {
G4cout << "### G4EmDataHandler::UpdateTable fail for idx=" << idx
<< " length=" << tLength << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4PhysicsTable* G4EmDataHandler::MakeTable(size_t i)
{
G4PhysicsTable* table = nullptr;
size_t idx = i;
if(idx >= tLength) {
data.push_back(nullptr);
idx = tLength;
++tLength;
}
data[idx] = G4PhysicsTableHelper::PreparePhysicsTable(data[idx]);
return data[idx];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4PhysicsTable* G4EmDataHandler::MakeTable(G4PhysicsTable* ptr, size_t i)
{
size_t idx = i;
// create new table only if index corresponds to the
// position in the vector
if(i <= tLength) {
if(i < tLength) { table = data[i]; }
table = G4PhysicsTableHelper::PreparePhysicsTable(table);
if(i == tLength) {
data.push_back(table);
++tLength;
} else { data[i] = table; }
if(idx < tLength) {
if(ptr != data[idx]) {
CleanTable(idx);
data[idx] = ptr;
}
} else {
data.push_back(ptr);
idx = tLength;
++tLength;
}
return table;
data[idx] = G4PhysicsTableHelper::PreparePhysicsTable(ptr);
return data[idx];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmDataHandler::CleanTable(size_t i)
{
//std::cout << i << " " << data[i] << std::endl;
if(i < tLength && nullptr != data[i]) {
data[i]->clearAndDestroy();
delete data[i];
@@ -114,11 +146,11 @@ G4bool G4EmDataHandler::StorePhysicsTable(size_t idx,
yes = data[idx]->StorePhysicsTable(fname, ascii);
if ( yes ) {
G4cout << "Physics table is stored for "
G4cout << "### Physics table is stored for "
<< part->GetParticleName()
<< " <" << fname << "> " << G4endl;
} else {
G4cout << "Fail to store Physics Table for "
G4cout << "### Fail to store Physics Table for "
<< part->GetParticleName()
<< " <" << fname << "> " << G4endl;
}
@@ -131,20 +163,20 @@ G4bool G4EmDataHandler::StorePhysicsTable(size_t idx,
G4bool G4EmDataHandler::RetrievePhysicsTable(size_t idx,
const G4ParticleDefinition* part,
const G4String& fname,
G4bool ascii, G4bool spline)
G4bool ascii, G4bool spline)
{
G4PhysicsTable* table = Table(idx);
G4bool yes = G4PhysicsTableHelper::RetrievePhysicsTable(table, fname, ascii, spline);
G4EmParameters* param = G4EmParameters::Instance();
if ( yes ) {
if (0 < param->Verbose()) {
G4cout << "Physics table " << idx << " for "
G4cout << "### Physics table " << idx << " for "
<< part->GetParticleName()
<< " is retrieved from <" << fname << ">"
<< G4endl;
}
} else if (1 < param->Verbose()) {
G4cout << "Fail to retrieve physics table " << idx << " for "
G4cout << "### Fail to retrieve physics table " << idx << " for "
<< part->GetParticleName() << " from <"
<< fname << ">" << G4endl;
}
@@ -65,10 +65,10 @@ G4EmElementSelector::G4EmElementSelector(G4VEmModel* mod,
theElementVector = material->GetElementVector();
if(nElmMinusOne > 0) {
xSections.reserve(n);
G4PhysicsLogVector* v0 = new G4PhysicsLogVector(lowEnergy,highEnergy,nbins,false);
auto v0 = new G4PhysicsLogVector(lowEnergy,highEnergy,nbins,false);
xSections.push_back(v0);
for(G4int i=1; i<n; ++i) {
G4PhysicsLogVector* v = new G4PhysicsLogVector(*v0);
auto v = new G4PhysicsLogVector(*v0);
xSections.push_back(v);
}
}
@@ -66,13 +66,13 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
paiCmd->AvailableForStates(G4State_PreInit);
paiCmd->SetToBeBroadcasted(false);
G4UIparameter* part = new G4UIparameter("partName",'s',false);
auto part = new G4UIparameter("partName",'s',false);
paiCmd->SetParameter(part);
G4UIparameter* pregName = new G4UIparameter("regName",'s',false);
auto pregName = new G4UIparameter("regName",'s',false);
paiCmd->SetParameter(pregName);
G4UIparameter* ptype = new G4UIparameter("type",'s',false);
auto ptype = new G4UIparameter("type",'s',false);
paiCmd->SetParameter(ptype);
ptype->SetParameterCandidates("pai PAI PAIphoton");
@@ -82,10 +82,10 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
mscoCmd->SetGuidance(" emType : G4EmStandard, G4EmStandard_opt1, ...");
mscoCmd->AvailableForStates(G4State_PreInit);
G4UIparameter* mregName = new G4UIparameter("regName",'s',false);
auto mregName = new G4UIparameter("regName",'s',false);
mscoCmd->SetParameter(mregName);
G4UIparameter* mtype = new G4UIparameter("mscType",'s',false);
auto mtype = new G4UIparameter("mscType",'s',false);
mscoCmd->SetParameter(mtype);
mtype->SetParameterCandidates("G4EmStandard G4EmStandard_opt1 G4EmStandard_opt2 G4EmStandard_opt3 G4EmStandard_opt4 G4EmStandardGS G4EmStandardSS G4EmLivermore G4EmPenelope G4RadioactiveDecay");
@@ -103,15 +103,15 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
StepFuncCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd->SetToBeBroadcasted(false);
G4UIparameter* dRoverRPrm = new G4UIparameter("dRoverR",'d',false);
auto dRoverRPrm = new G4UIparameter("dRoverR",'d',false);
dRoverRPrm->SetParameterRange("dRoverR>0. && dRoverR<=1.");
StepFuncCmd->SetParameter(dRoverRPrm);
G4UIparameter* finalRangePrm = new G4UIparameter("finalRange",'d',false);
auto finalRangePrm = new G4UIparameter("finalRange",'d',false);
finalRangePrm->SetParameterRange("finalRange>0.");
StepFuncCmd->SetParameter(finalRangePrm);
G4UIparameter* unitPrm = new G4UIparameter("unit",'s',true);
auto unitPrm = new G4UIparameter("unit",'s',true);
unitPrm->SetDefaultUnit("mm");
StepFuncCmd->SetParameter(unitPrm);
@@ -122,15 +122,15 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
StepFuncCmd1->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd1->SetToBeBroadcasted(false);
G4UIparameter* dRoverRPrm1 = new G4UIparameter("dRoverRMuHad",'d',false);
auto dRoverRPrm1 = new G4UIparameter("dRoverRMuHad",'d',false);
dRoverRPrm1->SetParameterRange("dRoverRMuHad>0. && dRoverRMuHad<=1.");
StepFuncCmd1->SetParameter(dRoverRPrm1);
G4UIparameter* finalRangePrm1 = new G4UIparameter("finalRangeMuHad",'d',false);
auto finalRangePrm1 = new G4UIparameter("finalRangeMuHad",'d',false);
finalRangePrm1->SetParameterRange("finalRangeMuHad>0.");
StepFuncCmd1->SetParameter(finalRangePrm1);
G4UIparameter* unitPrm1 = new G4UIparameter("unit",'s',true);
auto unitPrm1 = new G4UIparameter("unit",'s',true);
unitPrm1->SetDefaultValue("mm");
StepFuncCmd1->SetParameter(unitPrm1);
@@ -141,15 +141,15 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
StepFuncCmd2->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd2->SetToBeBroadcasted(false);
G4UIparameter* dRoverRPrm2 = new G4UIparameter("dRoverRLIons",'d',false);
auto dRoverRPrm2 = new G4UIparameter("dRoverRLIons",'d',false);
dRoverRPrm2->SetParameterRange("dRoverRLIons>0. && dRoverRLIons<=1.");
StepFuncCmd2->SetParameter(dRoverRPrm2);
G4UIparameter* finalRangePrm2 = new G4UIparameter("finalRangeLIons",'d',false);
auto finalRangePrm2 = new G4UIparameter("finalRangeLIons",'d',false);
finalRangePrm2->SetParameterRange("finalRangeLIons>0.");
StepFuncCmd2->SetParameter(finalRangePrm2);
G4UIparameter* unitPrm2 = new G4UIparameter("unit",'s',true);
auto unitPrm2 = new G4UIparameter("unit",'s',true);
unitPrm2->SetDefaultValue("mm");
StepFuncCmd2->SetParameter(unitPrm2);
@@ -160,15 +160,15 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
StepFuncCmd3->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd3->SetToBeBroadcasted(false);
G4UIparameter* dRoverRPrm3 = new G4UIparameter("dRoverRMuHad",'d',false);
auto dRoverRPrm3 = new G4UIparameter("dRoverRIons",'d',false);
dRoverRPrm3->SetParameterRange("dRoverRIons>0. && dRoverRIons<=1.");
StepFuncCmd3->SetParameter(dRoverRPrm3);
G4UIparameter* finalRangePrm3 = new G4UIparameter("finalRangeIons",'d',false);
auto finalRangePrm3 = new G4UIparameter("finalRangeIons",'d',false);
finalRangePrm3->SetParameterRange("finalRangeIons>0.");
StepFuncCmd3->SetParameter(finalRangePrm3);
G4UIparameter* unitPrm3 = new G4UIparameter("unit",'s',true);
auto unitPrm3 = new G4UIparameter("unit",'s',true);
unitPrm3->SetDefaultValue("mm");
StepFuncCmd3->SetParameter(unitPrm3);
@@ -180,13 +180,13 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
bfCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
bfCmd->SetToBeBroadcasted(false);
G4UIparameter* procName = new G4UIparameter("procName",'s',false);
auto procName = new G4UIparameter("procName",'s',false);
bfCmd->SetParameter(procName);
G4UIparameter* procFact = new G4UIparameter("procFact",'d',false);
auto procFact = new G4UIparameter("procFact",'d',false);
bfCmd->SetParameter(procFact);
G4UIparameter* flagFact = new G4UIparameter("flagFact",'s',false);
auto flagFact = new G4UIparameter("flagFact",'s',false);
bfCmd->SetParameter(flagFact);
fiCmd = new G4UIcommand("/process/em/setForcedInteraction",this);
@@ -199,21 +199,21 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
fiCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
fiCmd->SetToBeBroadcasted(false);
G4UIparameter* procNam = new G4UIparameter("procNam",'s',false);
auto procNam = new G4UIparameter("procNam",'s',false);
fiCmd->SetParameter(procNam);
G4UIparameter* regNam = new G4UIparameter("regNam",'s',false);
auto regNam = new G4UIparameter("regNam",'s',false);
fiCmd->SetParameter(regNam);
G4UIparameter* tlength = new G4UIparameter("tlength",'d',false);
auto tlength = new G4UIparameter("tlength",'d',false);
tlength->SetParameterRange("tlength>0");
fiCmd->SetParameter(tlength);
G4UIparameter* unitT = new G4UIparameter("unitT",'s',true);
auto unitT = new G4UIparameter("unitT",'s',true);
unitT->SetDefaultUnit("mm");
fiCmd->SetParameter(unitT);
G4UIparameter* flagT = new G4UIparameter("tflag",'b',true);
auto flagT = new G4UIparameter("tflag",'b',true);
flagT->SetDefaultValue(true);
fiCmd->SetParameter(flagT);
@@ -227,19 +227,19 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
bsCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
bsCmd->SetToBeBroadcasted(false);
G4UIparameter* bProcNam = new G4UIparameter("bProcNam",'s',false);
auto bProcNam = new G4UIparameter("bProcNam",'s',false);
bsCmd->SetParameter(bProcNam);
G4UIparameter* bRegNam = new G4UIparameter("bRegNam",'s',false);
auto bRegNam = new G4UIparameter("bRegNam",'s',false);
bsCmd->SetParameter(bRegNam);
G4UIparameter* bFactor = new G4UIparameter("bFactor",'d',false);
auto bFactor = new G4UIparameter("bFactor",'d',false);
bsCmd->SetParameter(bFactor);
G4UIparameter* bEnergy = new G4UIparameter("bEnergy",'d',false);
auto bEnergy = new G4UIparameter("bEnergy",'d',false);
bsCmd->SetParameter(bEnergy);
G4UIparameter* bUnit = new G4UIparameter("bUnit",'s',true);
auto bUnit = new G4UIparameter("bUnit",'s',true);
bUnit->SetDefaultUnit("MeV");
bsCmd->SetParameter(bUnit);
@@ -81,7 +81,7 @@ void G4EmLowEParameters::Initialise()
namePIXE = "Empirical";
nameElectronPIXE = "Livermore";
livDataDir = "livermore";
livDataDir = "epics_2017";
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -169,10 +169,10 @@ G4EmLowEParametersMessenger::G4EmLowEParametersMessenger(G4EmLowEParameters* ptr
dnaCmd->AvailableForStates(G4State_PreInit);
dnaCmd->SetToBeBroadcasted(false);
G4UIparameter* regName = new G4UIparameter("regName",'s',false);
auto regName = new G4UIparameter("regName",'s',false);
dnaCmd->SetParameter(regName);
G4UIparameter* type = new G4UIparameter("dnaType",'s',false);
auto type = new G4UIparameter("dnaType",'s',false);
dnaCmd->SetParameter(type);
type->SetParameterCandidates("DNA_Opt0 DNA_Opt2 DNA_Opt4 DNA_Opt4a DNA_Opt6 DNA_Opt6a DNA_Opt7");
@@ -185,16 +185,16 @@ G4EmLowEParametersMessenger::G4EmLowEParametersMessenger(G4EmLowEParameters* ptr
deexCmd->AvailableForStates(G4State_PreInit,G4State_Init,G4State_Idle);
deexCmd->SetToBeBroadcasted(false);
G4UIparameter* regNameD = new G4UIparameter("regName",'s',false);
auto regNameD = new G4UIparameter("regName",'s',false);
deexCmd->SetParameter(regNameD);
G4UIparameter* flagFluo = new G4UIparameter("flagFluo",'s',false);
auto flagFluo = new G4UIparameter("flagFluo",'s',false);
deexCmd->SetParameter(flagFluo);
G4UIparameter* flagAuger = new G4UIparameter("flagAuger",'s',false);
auto flagAuger = new G4UIparameter("flagAuger",'s',false);
deexCmd->SetParameter(flagAuger);
G4UIparameter* flagPIXE = new G4UIparameter("flagPIXE",'s',false);
auto flagPIXE = new G4UIparameter("flagPIXE",'s',false);
deexCmd->SetParameter(flagPIXE);
}
@@ -147,32 +147,13 @@ void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::UpdateEmModel(const G4String& nam,
G4double emin, G4double emax)
{
if (nEmModels > 0) {
for(G4int i=0; i<nEmModels; ++i) {
if(nam == models[i]->GetName()) {
models[i]->SetLowEnergyLimit(emin);
models[i]->SetHighEnergyLimit(emax);
return;
}
}
}
G4cout << "G4EmModelManager::UpdateEmModel WARNING: no model <"
<< nam << "> is found out"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmModel* G4EmModelManager::GetModel(G4int i, G4bool ver)
G4VEmModel* G4EmModelManager::GetModel(G4int idx, G4bool ver) const
{
G4VEmModel* model = nullptr;
if(i < nEmModels) { model = models[i]; }
if(idx >= 0 && idx < nEmModels) { model = models[idx]; }
else if(verboseLevel > 0 && ver) {
G4cout << "G4EmModelManager::GetModel WARNING: "
<< "index " << i << " is wrong Nmodels= "
<< "index " << idx << " is wrong Nmodels= "
<< nEmModels;
if(nullptr != particle) {
G4cout << " for " << particle->GetParticleName();
@@ -203,7 +184,7 @@ G4int G4EmModelManager::NumberOfRegionModels(size_t idx) const
const G4DataVector*
G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* secondaryParticle,
G4double, G4int verb)
G4int verb)
{
verboseLevel = verb;
if(1 < verboseLevel) {
@@ -267,10 +248,10 @@ G4EmModelManager::Initialise(const G4ParticleDefinition* p,
// or only one region
if(nRegions > 1 && nEmModels > 1) {
idxOfRegionModels.resize(numOfCouples,0);
setOfRegionModels.resize((size_t)nRegions,0);
setOfRegionModels.resize((size_t)nRegions,nullptr);
} else {
idxOfRegionModels.resize(1,0);
setOfRegionModels.resize(1,0);
setOfRegionModels.resize(1,nullptr);
}
std::vector<G4int> modelAtRegion(nEmModels);
@@ -469,7 +450,7 @@ G4EmModelManager::Initialise(const G4ParticleDefinition* p,
for(G4int iii=0; iii<=n; ++iii) {G4cout << eLow[iii]/MeV << " ";}
G4cout << G4endl;
}
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow, region);
auto rm = new G4RegionModels(n, modelAtRegion, eLow, region);
setOfRegionModels[reg] = rm;
// shortcut
if(1 == nEmModels) { break; }
@@ -758,7 +739,7 @@ void G4EmModelManager::DumpModelList(std::ostream& out, G4int verb)
out << " Fluo";
}
out << G4endl;
G4VMscModel* msc = dynamic_cast<G4VMscModel*>(model);
auto msc = dynamic_cast<G4VMscModel*>(model);
if(msc != nullptr) msc->DumpParameters(out);
}
}
@@ -59,8 +59,7 @@ G4EmMultiModel::G4EmMultiModel(const G4String& nam)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmMultiModel::~G4EmMultiModel()
{}
G4EmMultiModel::~G4EmMultiModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -55,28 +55,27 @@
#include "G4Region.hh"
#include "G4ApplicationState.hh"
#include "G4StateManager.hh"
#include "G4Threading.hh"
#include "G4AutoLock.hh"
G4EmParameters* G4EmParameters::theInstance = nullptr;
#ifdef G4MULTITHREADED
G4Mutex G4EmParameters::emParametersMutex = G4MUTEX_INITIALIZER;
#endif
namespace
{
G4Mutex emParametersMutex = G4MUTEX_INITIALIZER;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4EmParameters* G4EmParameters::Instance()
{
if(nullptr == theInstance) {
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&emParametersMutex);
G4AutoLock l(&emParametersMutex);
if(nullptr == theInstance) {
#endif
static G4EmParameters manager;
theInstance = &manager;
#ifdef G4MULTITHREADED
}
G4MUTEXUNLOCK(&emParametersMutex);
#endif
l.unlock();
}
return theInstance;
}
@@ -165,10 +164,12 @@ void G4EmParameters::Initialise()
workerVerbose = 0;
tripletConv = 0;
fTransportationWithMsc = G4TransportationWithMscType::fDisabled;
mscStepLimit = fUseSafety;
mscStepLimitMuHad = fMinimal;
nucFormfactor = fExponentialNF;
fSStype = fWVI;
fFluct = fUniversalFluctuation;
}
void G4EmParameters::SetLossFluctuations(G4bool val)
@@ -952,6 +953,28 @@ G4int G4EmParameters::WorkerVerbose() const
return workerVerbose;
}
void G4EmParameters::SetTransportationWithMsc(G4TransportationWithMscType val)
{
if(IsLocked()) { return; }
fTransportationWithMsc = val;
}
G4TransportationWithMscType G4EmParameters::TransportationWithMsc() const
{
return fTransportationWithMsc;
}
void G4EmParameters::SetFluctuationType(G4EmFluctuationType val)
{
if(IsLocked()) { return; }
fFluct = val;
}
G4EmFluctuationType G4EmParameters::FluctuationType() const
{
return fFluct;
}
void G4EmParameters::SetMscStepLimitType(G4MscStepLimitType val)
{
if(IsLocked()) { return; }
@@ -1234,6 +1257,13 @@ void G4EmParameters::StreamInfo(std::ostream& os) const
os << "LPM effect enabled " <<flagLPM << "\n";
os << "Enable creation and use of sampling tables " <<fSamplingTable << "\n";
os << "Apply cuts on all EM processes " <<applyCuts << "\n";
const char* transportationWithMsc = "Disabled";
if(fTransportationWithMsc == G4TransportationWithMscType::fEnabled) {
transportationWithMsc = "Enabled";
} else if (fTransportationWithMsc == G4TransportationWithMscType::fMultipleSteps) {
transportationWithMsc = "MultipleSteps";
}
os << "Use combined TransportationWithMsc " <<transportationWithMsc << "\n";
os << "Use general process " <<gener << "\n";
os << "Enable linear polarisation for gamma " <<fPolarisation << "\n";
os << "Enable sampling of quantum entanglement "
@@ -1283,8 +1313,9 @@ void G4EmParameters::StreamInfo(std::ostream& os) const
<<G4BestUnit(lowestElectronEnergy,"Energy") << "\n";
os << "Lowest muon/hadron kinetic energy "
<<G4BestUnit(lowestMuHadEnergy,"Energy") << "\n";
os << "Fluctuations of dE/dx are enabled " <<lossFluctuation << "\n";
os << "Use ICRU90 data " << fICRU90 << "\n";
os << "Fluctuations of dE/dx are enabled " <<lossFluctuation << "\n";
os << "Type of fluctuation model " << fFluct << "\n";
os << "Use built-in Birks satuaration " << birks << "\n";
os << "Build CSDA range enabled " <<buildCSDARange << "\n";
os << "Use cut as a final range enabled " <<cutAsFinalRange << "\n";
@@ -61,15 +61,15 @@
G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
: theParameters(ptr)
{
gconvDirectory = new G4UIdirectory("/process/gconv/");
gconvDirectory->SetGuidance("Commands for EM gamma conversion BH5D model.");
eLossDirectory = new G4UIdirectory("/process/eLoss/");
eLossDirectory->SetGuidance("Commands for EM processes.");
mscDirectory = new G4UIdirectory("/process/msc/");
mscDirectory->SetGuidance("Commands for EM scattering processes.");
emDirectory = new G4UIdirectory("/process/em/");
emDirectory = new G4UIdirectory("/process/em/", false);
emDirectory->SetGuidance("General commands for EM processes.");
dnaDirectory = new G4UIdirectory("/process/dna/");
eLossDirectory = new G4UIdirectory("/process/eLoss/", false);
eLossDirectory->SetGuidance("Commands for energy loss processes.");
mscDirectory = new G4UIdirectory("/process/msc/", false);
mscDirectory->SetGuidance("Commands for EM scattering processes.");
gconvDirectory = new G4UIdirectory("/process/gconv/", false);
gconvDirectory->SetGuidance("Commands for EM gamma conversion BH5D model.");
dnaDirectory = new G4UIdirectory("/process/dna/", false);
dnaDirectory->SetGuidance("Commands for DNA processes.");
flucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
@@ -107,6 +107,13 @@ G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
aplCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
aplCmd->SetToBeBroadcasted(false);
intCmd = new G4UIcmdWithABool("/process/em/integral",this);
intCmd->SetGuidance("Enable/disable integral method.");
intCmd->SetParameterName("choice",true);
intCmd->SetDefaultValue(true);
intCmd->AvailableForStates(G4State_PreInit);
intCmd->SetToBeBroadcasted(false);
latCmd = new G4UIcmdWithABool("/process/msc/LateralDisplacement",this);
latCmd->SetGuidance("Enable/disable sampling of lateral displacement");
latCmd->SetParameterName("lat",true);
@@ -142,7 +149,7 @@ G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
mottCmd->AvailableForStates(G4State_PreInit);
mottCmd->SetToBeBroadcasted(false);
birksCmd = new G4UIcmdWithABool("/process/msc/UseG4EmSaturation",this);
birksCmd = new G4UIcmdWithABool("/process/em/UseG4EmSaturation",this);
birksCmd->SetGuidance("Enable usage of built-in Birks saturation");
birksCmd->SetParameterName("birks",true);
birksCmd->SetDefaultValue(false);
@@ -363,6 +370,13 @@ G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
ver2Cmd->AvailableForStates(G4State_PreInit,G4State_Idle);
ver2Cmd->SetToBeBroadcasted(false);
transWithMscCmd = new G4UIcmdWithAString("/process/em/transportationWithMsc",this);
transWithMscCmd->SetGuidance("Enable/disable the G4TransportationWithMsc process");
transWithMscCmd->SetParameterName("trans",true);
transWithMscCmd->SetCandidates("Disabled Enabled MultipleSteps");
transWithMscCmd->AvailableForStates(G4State_PreInit);
transWithMscCmd->SetToBeBroadcasted(false);
mscCmd = new G4UIcmdWithAString("/process/msc/StepLimit",this);
mscCmd->SetGuidance("Set msc step limitation type");
mscCmd->SetParameterName("StepLim",true);
@@ -396,6 +410,13 @@ G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
ssCmd->AvailableForStates(G4State_PreInit);
ssCmd->SetToBeBroadcasted(false);
fluc1Cmd = new G4UIcmdWithAString("/process/eloss/setFluctModel",this);
fluc1Cmd->SetGuidance("Define type of energy loss fluctuation model");
fluc1Cmd->SetParameterName("Fluc1",true);
fluc1Cmd->SetCandidates("Dummy Universal Urban");
fluc1Cmd->AvailableForStates(G4State_PreInit);
fluc1Cmd->SetToBeBroadcasted(false);
tripletCmd = new G4UIcmdWithAnInteger("/process/gconv/conversionType",this);
tripletCmd->SetGuidance("gamma conversion triplet/nuclear generation type:");
tripletCmd->SetGuidance("0 - (default) both triplet and nuclear");
@@ -432,6 +453,7 @@ G4EmParametersMessenger::~G4EmParametersMessenger()
delete lpmCmd;
delete rsCmd;
delete aplCmd;
delete intCmd;
delete latCmd;
delete lat96Cmd;
delete mulatCmd;
@@ -472,12 +494,14 @@ G4EmParametersMessenger::~G4EmParametersMessenger()
delete verCmd;
delete ver1Cmd;
delete ver2Cmd;
delete transWithMscCmd;
delete tripletCmd;
delete mscCmd;
delete msc1Cmd;
delete nffCmd;
delete ssCmd;
delete fluc1Cmd;
delete dumpCmd;
}
@@ -502,6 +526,8 @@ void G4EmParametersMessenger::SetNewValue(G4UIcommand* command,
} else if (command == aplCmd) {
theParameters->SetApplyCuts(aplCmd->GetNewBoolValue(newValue));
physicsModified = true;
} else if (command == intCmd) {
theParameters->SetIntegral(intCmd->GetNewBoolValue(newValue));
} else if (command == latCmd) {
theParameters->SetLateralDisplacement(latCmd->GetNewBoolValue(newValue));
physicsModified = true;
@@ -593,6 +619,20 @@ void G4EmParametersMessenger::SetNewValue(G4UIcommand* command,
} else if (command == dumpCmd) {
theParameters->SetIsPrintedFlag(false);
theParameters->Dump();
} else if (command == transWithMscCmd) {
G4TransportationWithMscType type = G4TransportationWithMscType::fDisabled;
if(newValue == "Disabled") {
type = G4TransportationWithMscType::fDisabled;
} else if(newValue == "Enabled") {
type = G4TransportationWithMscType::fEnabled;
} else if(newValue == "MultipleSteps") {
type = G4TransportationWithMscType::fMultipleSteps;
} else {
G4ExceptionDescription ed;
ed << " TransportationWithMsc type <" << newValue << "> unknown!";
G4Exception("G4EmParametersMessenger", "em0044", JustWarning, ed);
}
theParameters->SetTransportationWithMsc(type);
} else if (command == mscCmd || command == msc1Cmd) {
G4MscStepLimitType msctype = fUseSafety;
if(newValue == "Minimal") {
@@ -638,6 +678,11 @@ void G4EmParametersMessenger::SetNewValue(G4UIcommand* command,
return;
}
theParameters->SetSingleScatteringType(x);
} else if (command == fluc1Cmd) {
G4EmFluctuationType x = fUniversalFluctuation;
if(newValue == "Dummy") { x = fDummyFluctuation; }
else if(newValue == "Urban") { x = fUrbanFluctuation; }
theParameters->SetFluctuationType(x);
} else if ( command==tripletCmd ) {
theParameters->SetConversionType(tripletCmd->GetNewIntValue(newValue));
} else if ( command==onIsolatedCmd ) {
@@ -72,8 +72,7 @@ G4EmSaturation::G4EmSaturation(G4int verb)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmSaturation::~G4EmSaturation()
{}
G4EmSaturation::~G4EmSaturation() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,695 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Geant4 class G4EmTableUtil
//
// Author V.Ivanchenko 14.03.2022
//
#include "G4EmTableUtil.hh"
#include "G4RegionStore.hh"
#include "G4ProductionCutsTable.hh"
#include "G4EmParameters.hh"
#include "G4EmUtility.hh"
#include "G4LossTableManager.hh"
#include "G4EmTableType.hh"
#include "G4PhysicsModelCatalog.hh"
#include "G4LowEnergyEmProcessSubType.hh"
#include "G4PhysicsTableHelper.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ProcessManager.hh"
#include "G4UIcommand.hh"
#include "G4GenericIon.hh"
#include <iostream>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
const G4DataVector*
G4EmTableUtil::PrepareEmProcess(G4VEmProcess* proc,
const G4ParticleDefinition* part,
const G4ParticleDefinition* secPart,
G4EmModelManager* modelManager,
const G4double& maxKinEnergy,
G4int& secID, G4int& tripletID,
G4int& mainSec, const G4int& verb,
const G4bool& master)
{
G4EmParameters* param = G4EmParameters::Instance();
// initialisation of models
G4double plimit = param->MscThetaLimit();
G4int nModels = modelManager->NumberOfModels();
for(G4int i=0; i<nModels; ++i) {
G4VEmModel* mod = modelManager->GetModel(i);
if(nullptr == mod) { continue; }
mod->SetPolarAngleLimit(plimit);
mod->SetMasterThread(master);
if(mod->HighEnergyLimit() > maxKinEnergy) {
mod->SetHighEnergyLimit(maxKinEnergy);
}
proc->SetEmModel(mod);
}
// defined ID of secondary particles and verbosity
G4int stype = proc->GetProcessSubType();
if(stype == fAnnihilation) {
secID = _Annihilation;
tripletID = _TripletGamma;
} else if(stype == fGammaConversion) {
secID = _PairProduction;
mainSec = 2;
} else if(stype == fPhotoElectricEffect) {
secID = _PhotoElectron;
} else if(stype == fComptonScattering) {
secID = _ComptonElectron;
} else if(stype >= fLowEnergyElastic) {
secID = fDNAUnknownModel;
}
if(master) {
proc->SetVerboseLevel(param->Verbose());
} else {
proc->SetVerboseLevel(param->WorkerVerbose());
}
// model initialisation
const G4DataVector* cuts = modelManager->Initialise(part, secPart, verb);
if(1 < verb) {
G4cout << "### G4VEmProcess::PreparePhysicsTable() done for "
<< proc->GetProcessName()
<< " and particle " << part->GetParticleName()
<< G4endl;
}
return cuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::BuildEmProcess(G4VEmProcess* proc,
const G4VEmProcess* masterProc,
const G4ParticleDefinition* firstPart,
const G4ParticleDefinition* part,
const G4int nModels, const G4int verb,
const G4bool master, const G4bool isLocked,
const G4bool toBuild, G4bool& baseMat)
{
G4String num = part->GetParticleName();
if(1 < verb) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() for "
<< proc->GetProcessName() << " and particle " << num
<< " buildLambdaTable=" << toBuild << " master= " << master
<< G4endl;
}
if(firstPart == part) {
// worker initialisation
if(!master) {
proc->SetLambdaTable(masterProc->LambdaTable());
proc->SetLambdaTablePrim(masterProc->LambdaTablePrim());
proc->SetCrossSectionType(masterProc->CrossSectionType());
proc->SetEnergyOfCrossSectionMax(masterProc->EnergyOfCrossSectionMax());
// local initialisation of models
baseMat = masterProc->UseBaseMaterial();
G4bool printing = true;
for(G4int i=0; i<nModels; ++i) {
G4VEmModel* mod = proc->GetModelByIndex(i, printing);
G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing);
mod->SetUseBaseMaterials(baseMat);
mod->InitialiseLocal(part, mod0);
}
// master thread
} else {
if(toBuild) { proc->BuildLambdaTable(); }
auto fXSType = proc->CrossSectionType();
auto v = proc->EnergyOfCrossSectionMax();
delete v;
v = nullptr;
if(fXSType == fEmOnePeak) {
auto table = proc->LambdaTable();
if(nullptr == table) {
v = G4EmUtility::FindCrossSectionMax(proc, part);
} else {
v = G4EmUtility::FindCrossSectionMax(table);
}
if(nullptr == v) { proc->SetCrossSectionType(fEmIncreasing); }
}
proc->SetEnergyOfCrossSectionMax(v);
}
}
// protection against double printout
if(isLocked) { return; }
// explicitly defined printout by particle name
if(1 < verb || (0 < verb && (num == "gamma" || num == "e-" ||
num == "e+" || num == "mu+" ||
num == "mu-" || num == "proton"||
num == "pi+" || num == "pi-" ||
num == "kaon+" || num == "kaon-" ||
num == "alpha" || num == "anti_proton" ||
num == "GenericIon" ||
num == "alpha+" || num == "helium" ||
num == "hydrogen"))) {
proc->StreamInfo(G4cout, *part);
}
if(1 < verb) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() done for "
<< proc->GetProcessName() << " and particle " << num
<< " baseMat=" << baseMat << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::BuildLambdaTable(G4VEmProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* theLambdaTable,
G4PhysicsTable* theLambdaTablePrim,
const G4double minKinEnergy,
const G4double minKinEnergyPrim,
const G4double maxKinEnergy,
const G4double scale,
const G4int verboseLevel,
const G4bool startFromNull,
const G4bool splineFlag)
{
if(1 < verboseLevel) {
G4cout << "G4EmProcess::BuildLambdaTable() for process "
<< proc->GetProcessName() << " and particle "
<< part->GetParticleName() << G4endl;
}
// Access to materials
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4PhysicsLogVector* aVector = nullptr;
G4PhysicsLogVector* aVectorPrim = nullptr;
G4PhysicsLogVector* bVectorPrim = nullptr;
G4double emax1 = std::min(maxKinEnergy, minKinEnergyPrim);
for(size_t i=0; i<numOfCouples; ++i) {
if (bld->GetFlag(i)) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
// build main table
if(nullptr != theLambdaTable) {
delete (*theLambdaTable)[i];
// if start from zero then change the scale
G4double emin = minKinEnergy;
G4bool startNull = false;
if(startFromNull) {
G4double e = proc->MinPrimaryEnergy(part, couple->GetMaterial());
if(e >= emin) {
emin = e;
startNull = true;
}
}
G4double emax = emax1;
if(emax <= emin) { emax = 2*emin; }
G4int bin = G4lrint(scale*G4Log(emax/emin));
bin = std::max(bin, 5);
aVector = new G4PhysicsLogVector(emin, emax, bin, splineFlag);
modelManager->FillLambdaVector(aVector, couple, startNull);
if(splineFlag) { aVector->FillSecondDerivatives(); }
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector);
}
// build high energy table
if(nullptr != theLambdaTablePrim) {
delete (*theLambdaTablePrim)[i];
// start not from zero and always use spline
if(nullptr == bVectorPrim) {
G4int bin = G4lrint(scale*G4Log(maxKinEnergy/minKinEnergyPrim));
bin = std::max(bin, 5);
aVectorPrim =
new G4PhysicsLogVector(minKinEnergyPrim, maxKinEnergy, bin, true);
bVectorPrim = aVectorPrim;
} else {
aVectorPrim = new G4PhysicsLogVector(*bVectorPrim);
}
modelManager->FillLambdaVector(aVectorPrim, couple, false,
fIsCrossSectionPrim);
aVectorPrim->FillSecondDerivatives();
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTablePrim, i,
aVectorPrim);
}
}
}
if(1 < verboseLevel) {
G4cout << "Lambda table is built for " << part->GetParticleName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::BuildLambdaTable(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* theLambdaTable,
const G4DataVector* theCuts,
const G4double minKinEnergy,
const G4double maxKinEnergy,
const G4double scale,
const G4int verboseLevel,
const G4bool splineFlag)
{
if(1 < verboseLevel) {
G4cout << "G4EnergyLossProcess::BuildLambdaTable() for process "
<< proc->GetProcessName() << " and particle "
<< part->GetParticleName() << G4endl;
}
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4PhysicsLogVector* aVector = nullptr;
for(size_t i=0; i<numOfCouples; ++i) {
if (bld->GetFlag(i)) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
delete (*theLambdaTable)[i];
G4bool startNull = true;
G4double emin =
proc->MinPrimaryEnergy(part, couple->GetMaterial(), (*theCuts)[i]);
if(minKinEnergy > emin) {
emin = minKinEnergy;
startNull = false;
}
G4double emax = maxKinEnergy;
if(emax <= emin) { emax = 2*emin; }
G4int bin = G4lrint(scale*G4Log(emax/emin));
bin = std::max(bin, 5);
aVector = new G4PhysicsLogVector(emin, emax, bin, splineFlag);
modelManager->FillLambdaVector(aVector, couple, startNull, fRestricted);
if(splineFlag) { aVector->FillSecondDerivatives(); }
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector);
}
}
if(1 < verboseLevel) {
G4cout << "Lambda table is built for " << part->GetParticleName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
const G4ParticleDefinition*
G4EmTableUtil::CheckIon(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
const G4ParticleDefinition* partLocal,
const G4int verb, G4bool& isIon)
{
if(1 < verb) {
G4cout << "G4VEnergyLossProcess::PreparePhysicsTable for "
<< proc->GetProcessName() << " for " << part->GetParticleName()
<< G4endl;
}
const G4ParticleDefinition* particle = partLocal;
// Are particle defined?
if(nullptr == particle) { particle = part; }
if(part->GetParticleType() == "nucleus") {
G4String pname = part->GetParticleName();
if(pname != "deuteron" && pname != "triton" &&
pname != "alpha+" && pname != "alpha") {
const G4ParticleDefinition* theGIon = G4GenericIon::GenericIon();
isIon = true;
if(particle != theGIon) {
G4ProcessManager* pm = theGIon->GetProcessManager();
G4ProcessVector* v = pm->GetAlongStepProcessVector();
size_t n = v->size();
for(size_t j=0; j<n; ++j) {
if((*v)[j] == proc) {
particle = theGIon;
break;
}
}
}
}
}
return particle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::UpdateModels(G4VEnergyLossProcess* proc,
G4EmModelManager* modelManager,
const G4double maxKinEnergy,
const G4int nModels,
G4int& secID, G4int& biasID,
G4int& mainSec, const G4bool baseMat,
const G4bool isMaster, const G4bool useAGen)
{
// defined ID of secondary particles
G4int stype = proc->GetProcessSubType();
if(stype == fBremsstrahlung) {
secID = _Bremsstrahlung;
biasID = _SplitBremsstrahlung;
} else if(stype == fPairProdByCharged) {
secID = _PairProduction;
mainSec = 2;
}
// initialisation of models
for(G4int i=0; i<nModels; ++i) {
G4VEmModel* mod = modelManager->GetModel(i);
mod->SetMasterThread(isMaster);
mod->SetAngularGeneratorFlag(useAGen);
if(mod->HighEnergyLimit() > maxKinEnergy) {
mod->SetHighEnergyLimit(maxKinEnergy);
}
mod->SetUseBaseMaterials(baseMat);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void
G4EmTableUtil::BuildLocalElossProcess(G4VEnergyLossProcess* proc,
const G4VEnergyLossProcess* masterProc,
const G4ParticleDefinition* part,
const G4int nModels)
{
// copy table pointers from master thread
proc->SetDEDXTable(masterProc->DEDXTable(),fRestricted);
proc->SetDEDXTable(masterProc->DEDXunRestrictedTable(),fTotal);
proc->SetDEDXTable(masterProc->IonisationTable(),fIsIonisation);
proc->SetRangeTableForLoss(masterProc->RangeTableForLoss());
proc->SetCSDARangeTable(masterProc->CSDARangeTable());
proc->SetInverseRangeTable(masterProc->InverseRangeTable());
proc->SetLambdaTable(masterProc->LambdaTable());
proc->SetCrossSectionType(masterProc->CrossSectionType());
proc->SetEnergyOfCrossSectionMax(masterProc->EnergyOfCrossSectionMax());
proc->SetTwoPeaksXS(masterProc->TwoPeaksXS());
proc->SetIonisation(masterProc->IsIonisationProcess());
G4bool baseMat = masterProc->UseBaseMaterial();
// local initialisation of models
G4bool printing = true;
for(G4int i=0; i<nModels; ++i) {
G4VEmModel* mod = proc->GetModelByIndex(i, printing);
G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing);
mod->SetUseBaseMaterials(baseMat);
mod->InitialiseLocal(part, mod0);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::BuildDEDXTable(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* part,
G4EmModelManager* modelManager,
G4LossTableBuilder* bld,
G4PhysicsTable* table,
const G4double emin,
const G4double emax,
const G4int nbins,
const G4int verbose,
const G4EmTableType tType,
const G4bool spline)
{
// Access to materials
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if(1 < verbose) {
G4cout << numOfCouples << " couples" << " minKinEnergy(MeV)= " << emin
<< " maxKinEnergy(MeV)= " << emax << " nbins= " << nbins << G4endl;
}
G4PhysicsLogVector* aVector = nullptr;
G4PhysicsLogVector* bVector = nullptr;
for(size_t i=0; i<numOfCouples; ++i) {
if(1 < verbose) {
G4cout << "G4VEnergyLossProcess::BuildDEDXVector idx= " << i
<< " flagTable=" << table->GetFlag(i)
<< " flagBuilder=" << bld->GetFlag(i) << G4endl;
}
if(bld->GetFlag(i)) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
delete (*table)[i];
if(nullptr != bVector) {
aVector = new G4PhysicsLogVector(*bVector);
} else {
bVector = new G4PhysicsLogVector(emin, emax, nbins, spline);
aVector = bVector;
}
modelManager->FillDEDXVector(aVector, couple, tType);
if(spline) { aVector->FillSecondDerivatives(); }
// Insert vector for this material into the table
G4PhysicsTableHelper::SetPhysicsVector(table, i, aVector);
}
}
if(1 < verbose) {
G4cout << "G4VEnergyLossProcess::BuildDEDXTable(): table is built for "
<< part->GetParticleName()
<< " and process " << proc->GetProcessName()
<< G4endl;
if(2 < verbose) G4cout << (*table) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::PrepareMscProcess(G4VMultipleScattering* proc,
const G4ParticleDefinition& part,
G4EmModelManager* modelManager,
G4MscStepLimitType& stepLimit,
G4double& facrange,
G4bool& latDisplacement, G4bool& master,
G4bool& isIon, G4bool& baseMat)
{
auto param = G4EmParameters::Instance();
G4int verb = (master) ? param->Verbose() : param->WorkerVerbose();
proc->SetVerboseLevel(verb);
if(part.GetPDGMass() > CLHEP::GeV ||
part.GetParticleName() == "GenericIon") { isIon = true; }
if(1 < verb) {
G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for "
<< proc->GetProcessName()
<< " and particle " << part.GetParticleName()
<< " isIon: " << isIon << " isMaster: " << master
<< G4endl;
}
// initialise process
proc->InitialiseProcess(&part);
// heavy particles
if(part.GetPDGMass() > CLHEP::MeV) {
stepLimit = param->MscMuHadStepLimitType();
facrange = param->MscMuHadRangeFactor();
latDisplacement = param->MuHadLateralDisplacement();
} else {
stepLimit = param->MscStepLimitType();
facrange = param->MscRangeFactor();
latDisplacement = param->LateralDisplacement();
}
// initialisation of models
auto numberOfModels = modelManager->NumberOfModels();
for(G4int i=0; i<numberOfModels; ++i) {
G4VMscModel* msc = proc->GetModelByIndex(i);
msc->SetIonisation(nullptr, &part);
msc->SetMasterThread(master);
msc->SetPolarAngleLimit(param->MscThetaLimit());
G4double emax = std::min(msc->HighEnergyLimit(),param->MaxKinEnergy());
msc->SetHighEnergyLimit(emax);
msc->SetUseBaseMaterials(baseMat);
}
modelManager->Initialise(&part, nullptr, verb);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmTableUtil::BuildMscProcess(G4VMultipleScattering* proc,
const G4VMultipleScattering* masterProc,
const G4ParticleDefinition& part,
const G4ParticleDefinition* firstPart,
G4int nModels, G4bool master)
{
auto param = G4EmParameters::Instance();
G4int verb = param->Verbose();
if(!master && firstPart == &part) {
// initialisation of models
G4bool baseMat = masterProc->UseBaseMaterial();
for(G4int i=0; i<nModels; ++i) {
G4VMscModel* msc = proc->GetModelByIndex(i);
G4VMscModel* msc0 = masterProc->GetModelByIndex(i);
msc->SetUseBaseMaterials(baseMat);
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
msc->InitialiseLocal(&part, msc0);
}
}
if(!param->IsPrintLocked()) {
const G4String& num = part.GetParticleName();
// explicitly defined printout by particle name
if(1 < verb || (0 < verb && (num == "e-" ||
num == "e+" || num == "mu+" ||
num == "mu-" || num == "proton"||
num == "pi+" || num == "pi-" ||
num == "kaon+" || num == "kaon-" ||
num == "alpha" || num == "anti_proton" ||
num == "GenericIon" || num == "alpha+" ||
num == "alpha" ))) {
proc->StreamInfo(G4cout, part);
}
}
if(1 < verb) {
G4cout << "### G4VMultipleScattering::BuildPhysicsTable() done for "
<< proc->GetProcessName()
<< " and particle " << part.GetParticleName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4EmTableUtil::StoreMscTable(G4VMultipleScattering* proc,
const G4ParticleDefinition* part,
const G4String& dir,
const G4int nModels, const G4int verb,
const G4bool ascii)
{
G4bool ok = true;
for(G4int i=0; i<nModels; ++i) {
G4VMscModel* msc = proc->GetModelByIndex(i);
G4PhysicsTable* table = msc->GetCrossSectionTable();
if (nullptr != table) {
G4String ss = G4UIcommand::ConvertToString(i);
G4String name =
proc->GetPhysicsTableFileName(part, dir, "LambdaMod"+ss, ascii);
G4bool yes = table->StorePhysicsTable(name,ascii);
if ( yes ) {
if ( verb > 0 ) {
G4cout << "Physics table are stored for "
<< part->GetParticleName()
<< " and process " << proc->GetProcessName()
<< " with a name <" << name << "> " << G4endl;
}
} else {
G4cout << "Fail to store Physics Table for "
<< part->GetParticleName()
<< " and process " << proc->GetProcessName()
<< " in the directory <" << dir
<< "> " << G4endl;
ok = false;
}
}
}
return ok;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4EmTableUtil::StoreTable(G4VProcess* ptr,
const G4ParticleDefinition* part,
G4PhysicsTable* aTable,
const G4String& dir,
const G4String& tname,
const G4int verb, const G4bool ascii)
{
G4bool res = true;
if (nullptr != aTable) {
const G4String& name =
ptr->GetPhysicsTableFileName(part, dir, tname, ascii);
if ( aTable->StorePhysicsTable(name, ascii) ) {
if (1 < verb) G4cout << "Stored: " << name << G4endl;
} else {
res = false;
G4cout << "Fail to store: " << name << G4endl;
}
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4EmTableUtil::RetrieveTable(G4VProcess* ptr,
const G4ParticleDefinition* part,
G4PhysicsTable* aTable,
const G4String& dir, const G4String& tname,
const G4int verb, const G4bool ascii,
const G4bool spline)
{
G4bool res = true;
if (nullptr == aTable) { return res; }
G4cout << tname << " table for " << part->GetParticleName()
<< " will be retrieved " << G4endl;
const G4String& name =
ptr->GetPhysicsTableFileName(part, dir, tname, ascii);
if(G4PhysicsTableHelper::RetrievePhysicsTable(aTable, name, ascii, spline)) {
if(spline) {
for(auto & v : *aTable) {
if(nullptr != v) { v->FillSecondDerivatives(); }
}
}
if (0 < verb) {
G4cout << tname << " table for " << part->GetParticleName()
<< " is Retrieved from <" << name << ">"
<< G4endl;
}
} else {
res = false;
G4cout << "Fail to retrieve: " << tname << " from " << name << " for "
<< part->GetParticleName() << G4endl;
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,395 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Geant4 class G4EmUtility
//
// Author V.Ivanchenko 14.03.2022
//
#include "G4EmUtility.hh"
#include "G4RegionStore.hh"
#include "G4ProductionCutsTable.hh"
#include "G4VEmProcess.hh"
#include "G4EmParameters.hh"
#include "G4PhysicsVector.hh"
#include "Randomize.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
static const G4double g4log10 = G4Log(10.);
const G4Region*
G4EmUtility::FindRegion(const G4String& regionName, const G4int verbose)
{
const G4Region* reg = nullptr;
G4RegionStore* regStore = G4RegionStore::GetInstance();
G4String r = regionName;
if(r == "") { r = "DefaultRegionForTheWorld"; }
reg = regStore->GetRegion(r, true);
if(nullptr == reg && verbose > 0) {
G4cout << "### G4EmUtility WARNING: fails to find a region <"
<< r << G4endl;
} else if(verbose > 1) {
G4cout << "### G4EmUtility finds out G4Region <" << r << ">"
<< G4endl;
}
return reg;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
const G4Element* G4EmUtility::SampleRandomElement(const G4Material* mat)
{
const G4Element* elm = mat->GetElement(0);
size_t nElements = mat->GetNumberOfElements();
if(1 < nElements) {
G4double x = mat->GetTotNbOfElectPerVolume()*G4UniformRand();
const G4double* y = mat->GetVecNbOfAtomsPerVolume();
for(size_t i=0; i<nElements; ++i) {
elm = mat->GetElement(i);
x -= y[i]*elm->GetZ();
if(x <= 0.0) { break; }
}
}
return elm;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
const G4Isotope* G4EmUtility::SampleRandomIsotope(const G4Element* elm)
{
const size_t ni = elm->GetNumberOfIsotopes();
const G4Isotope* iso = elm->GetIsotope(0);
if(ni > 1) {
const G4double* ab = elm->GetRelativeAbundanceVector();
G4double x = G4UniformRand();
for(size_t idx=0; idx<ni; ++idx) {
x -= ab[idx];
if (x <= 0.0) {
iso = elm->GetIsotope(idx);
break;
}
}
}
return iso;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
std::vector<G4double>* G4EmUtility::FindCrossSectionMax(G4PhysicsTable* p)
{
std::vector<G4double>* ptr = nullptr;
if(nullptr == p) { return ptr; }
const G4int n = p->length();
ptr = new std::vector<G4double>;
ptr->resize(n, DBL_MAX);
G4bool isPeak = false;
G4double e, ss, ee, xs;
// first loop on existing vectors
for (G4int i=0; i<n; ++i) {
const G4PhysicsVector* pv = (*p)[i];
xs = ee = 0.0;
if(nullptr != pv) {
G4int nb = pv->GetVectorLength();
for (G4int j=0; j<nb; ++j) {
e = pv->Energy(j);
ss = (*pv)(j);
if(ss >= xs) {
xs = ss;
ee = e;
continue;
} else {
isPeak = true;
(*ptr)[i] = ee;
break;
}
}
}
}
// there is no peak for any material
if(!isPeak) {
delete ptr;
ptr = nullptr;
}
return ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
std::vector<G4double>*
G4EmUtility::FindCrossSectionMax(G4VDiscreteProcess* p,
const G4ParticleDefinition* part)
{
std::vector<G4double>* ptr = nullptr;
if(nullptr == p || nullptr == part) { return ptr; }
/*
G4cout << "G4EmUtility::FindCrossSectionMax for "
<< p->GetProcessName() << " and " << part->GetParticleName() << G4endl;
*/
G4EmParameters* theParameters = G4EmParameters::Instance();
G4double tmin = theParameters->MinKinEnergy();
G4double tmax = theParameters->MaxKinEnergy();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t n = theCoupleTable->GetTableSize();
ptr = new std::vector<G4double>;
ptr->resize(n, DBL_MAX);
G4bool isPeak = false;
G4double scale = theParameters->NumberOfBinsPerDecade()/g4log10;
G4double e, sig, ee, x, sm, em, emin, emax;
// first loop on existing vectors
for (size_t i=0; i<n; ++i) {
auto couple = theCoupleTable->GetMaterialCutsCouple(i);
emin = std::max(p->MinPrimaryEnergy(part, couple->GetMaterial()), tmin);
emax = std::max(tmax, 2*emin);
ee = G4Log(emax/emin);
G4int nbin = G4lrint(ee*scale);
if(nbin < 4) { nbin = 4; }
x = G4Exp(ee/nbin);
sm = 0.0;
em = 0.0;
e = emin;
for(G4int j=0; j<=nbin; ++j) {
sig = p->GetCrossSection(e, couple);
if(sig >= sm) {
em = e;
sm = sig;
e = (j+1 < nbin) ? e*x : emax;
} else {
isPeak = true;
(*ptr)[i] = em;
break;
}
}
//G4cout << i << ". em=" << em << " sm=" << sm << G4endl;
}
// there is no peak for any couple
if(!isPeak) {
delete ptr;
ptr = nullptr;
}
return ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
std::vector<G4TwoPeaksXS*>*
G4EmUtility::FillPeaksStructure(G4PhysicsTable* p, G4LossTableBuilder* bld)
{
std::vector<G4TwoPeaksXS*>* ptr = nullptr;
if(nullptr == p) { return ptr; }
const G4int n = p->length();
ptr = new std::vector<G4TwoPeaksXS*>;
ptr->resize(n, nullptr);
G4double e, ss, xs, ee;
G4double e1peak, e1deep, e2peak, e2deep, e3peak;
G4bool isDeep = false;
// first loop on existing vectors
for (G4int i=0; i<n; ++i) {
const G4PhysicsVector* pv = (*p)[i];
ee = xs = 0.0;
e1peak = e1deep = e2peak = e2deep = e3peak = DBL_MAX;
if(nullptr != pv) {
G4int nb = pv->GetVectorLength();
for (G4int j=0; j<nb; ++j) {
e = pv->Energy(j);
ss = (*pv)(j);
// find out 1st peak
if(e1peak == DBL_MAX) {
if(ss >= xs) {
xs = ss;
ee = e;
continue;
} else {
e1peak = ee;
}
}
// find out the deep
if(e1deep == DBL_MAX) {
if(ss <= xs) {
xs = ss;
ee = e;
continue;
} else {
e1deep = ee;
isDeep = true;
}
}
// find out 2nd peak
if(e2peak == DBL_MAX) {
if(ss >= xs) {
xs = ss;
ee = e;
continue;
} else {
e2peak = ee;
}
}
if(e2deep == DBL_MAX) {
if(ss <= xs) {
xs = ss;
ee = e;
continue;
} else {
e2deep = ee;
break;
}
}
// find out 3d peak
if(e3peak == DBL_MAX) {
if(ss >= xs) {
xs = ss;
ee = e;
continue;
} else {
e3peak = ee;
}
}
}
}
G4TwoPeaksXS* x = (*ptr)[i];
if(nullptr == x) {
x = new G4TwoPeaksXS();
(*ptr)[i] = x;
}
x->e1peak = e1peak;
x->e1deep = e1deep;
x->e2peak = e2peak;
x->e2deep = e2deep;
x->e3peak = e3peak;
}
// case of no 1st peak in all vectors
if(!isDeep) {
delete ptr;
ptr = nullptr;
return ptr;
}
// check base particles
if(!bld->GetBaseMaterialFlag()) { return ptr; }
auto theDensityIdx = bld->GetCoupleIndexes();
// second loop using base materials
for (G4int i=0; i<n; ++i) {
const G4PhysicsVector* pv = (*p)[i];
if (nullptr == pv) {
G4int j = (*theDensityIdx)[i];
if(j == i) { continue; }
G4TwoPeaksXS* x = (*ptr)[i];
G4TwoPeaksXS* y = (*ptr)[j];
if(nullptr == x) {
x = new G4TwoPeaksXS();
(*ptr)[i] = x;
}
x->e1peak = y->e1peak;
x->e1deep = y->e1deep;
x->e2peak = y->e2peak;
x->e2deep = y->e2deep;
x->e3peak = y->e3peak;
}
}
return ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4EmUtility::InitialiseElementSelectors(G4VEmModel* mod,
const G4ParticleDefinition* part,
const G4DataVector& cuts,
const G4double elow,
const G4double ehigh)
{
// using spline for element selectors should be investigated in details
// because small number of points may provide biased results
// large number of points requires significant increase of memory
G4bool spline = false;
G4int nbinsPerDec = G4EmParameters::Instance()->NumberOfBinsPerDecade();
G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
G4int numOfCouples = theCoupleTable->GetTableSize();
// prepare vector
auto elmSelectors = mod->GetElementSelectors();
if(nullptr == elmSelectors) {
elmSelectors = new std::vector<G4EmElementSelector*>;
}
G4int nSelectors = elmSelectors->size();
if(numOfCouples > nSelectors) {
for(G4int i=nSelectors; i<numOfCouples; ++i) {
elmSelectors->push_back(nullptr);
}
nSelectors = numOfCouples;
}
// initialise vector
for(G4int i=0; i<numOfCouples; ++i) {
// no need in element selectors for infinite cuts
if(cuts[i] == DBL_MAX) { continue; }
auto couple = theCoupleTable->GetMaterialCutsCouple(i);
auto mat = couple->GetMaterial();
mod->SetCurrentCouple(couple);
// selector already exist then delete
delete (*elmSelectors)[i];
G4double emin = std::max(elow, mod->MinPrimaryEnergy(mat, part, cuts[i]));
G4double emax = std::max(ehigh, 10*emin);
static const G4double invlog106 = 1.0/(6*G4Log(10.));
G4int nbins = G4lrint(nbinsPerDec*G4Log(emax/emin)*invlog106);
nbins = std::max(nbins, 3);
(*elmSelectors)[i] = new G4EmElementSelector(mod,mat,nbins,
emin,emax,spline);
((*elmSelectors)[i])->Initialise(part, cuts[i]);
/*
G4cout << "G4VEmModel::InitialiseElmSelectors i= " << i
<< " " << part->GetParticleName()
<< " for " << mod->GetName() << " cut= " << cuts[i]
<< " " << (*elmSelectors)[i] << G4endl;
((*elmSelectors)[i])->Dump(part);
*/
}
mod->SetElementSelectors(elmSelectors);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -49,9 +49,9 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EnergyLossTablesHelper *G4EnergyLossTables::t = 0;
G4EnergyLossTablesHelper *G4EnergyLossTables::null_loss = 0;
G4ParticleDefinition* G4EnergyLossTables::lastParticle = 0;
G4EnergyLossTablesHelper *G4EnergyLossTables::t = nullptr;
G4EnergyLossTablesHelper *G4EnergyLossTables::null_loss = nullptr;
G4ParticleDefinition* G4EnergyLossTables::lastParticle = nullptr;
G4double G4EnergyLossTables::QQPositron = 1.0; // e_squared
G4double G4EnergyLossTables::Chargesquare ;
G4int G4EnergyLossTables::oldIndex = -1 ;
@@ -62,7 +62,7 @@ G4int G4EnergyLossTables::let_counter = 0;
G4int G4EnergyLossTables::let_max_num_warnings = 100;
G4bool G4EnergyLossTables::first_loss = true;
G4EnergyLossTables::helper_map *G4EnergyLossTables::dict = 0;
G4EnergyLossTables::helper_map *G4EnergyLossTables::dict = nullptr;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -126,7 +126,8 @@ void G4EnergyLossTables::Register(
Chargesquare = (p->GetPDGCharge())*(p->GetPDGCharge())/
QQPositron ;
if (first_loss ) {
*null_loss = G4EnergyLossTablesHelper(0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0);
*null_loss = G4EnergyLossTablesHelper(
nullptr, nullptr, nullptr, nullptr, nullptr, 0.0, 0.0, 0.0, 0);
first_loss = false;
}
}
@@ -138,7 +139,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetDEDXTable(
{
if (!dict) dict = new G4EnergyLossTables::helper_map;
helper_map::iterator it;
if((it=dict->find(p))==dict->end()) return 0;
if((it=dict->find(p))==dict->end()) return nullptr;
return (*it).second.theDEDXTable;
}
@@ -149,7 +150,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetRangeTable(
{
if (!dict) dict = new G4EnergyLossTables::helper_map;
helper_map::iterator it;
if((it=dict->find(p))==dict->end()) return 0;
if((it=dict->find(p))==dict->end()) return nullptr;
return (*it).second.theRangeTable;
}
@@ -160,7 +161,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetInverseRangeTable(
{
if (!dict) dict = new G4EnergyLossTables::helper_map;
helper_map::iterator it;
if((it=dict->find(p))==dict->end()) return 0;
if((it=dict->find(p))==dict->end()) return nullptr;
return (*it).second.theInverseRangeTable;
}
@@ -171,7 +172,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetLabTimeTable(
{
if (!dict) dict = new G4EnergyLossTables::helper_map;
helper_map::iterator it;
if((it=dict->find(p))==dict->end()) return 0;
if((it=dict->find(p))==dict->end()) return nullptr;
return (*it).second.theLabTimeTable;
}
@@ -182,7 +183,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetProperTimeTable(
{
if (!dict) dict = new G4EnergyLossTables::helper_map;
helper_map::iterator it;
if((it=dict->find(p))==dict->end()) return 0;
if((it=dict->find(p))==dict->end()) return nullptr;
return (*it).second.theProperTimeTable;
}
@@ -159,10 +159,10 @@ G4LossTableBuilder::BuildDEDXTable(G4PhysicsTable* dedxTable,
if(0 >= nCouples) { return; }
for (size_t i=0; i<nCouples; ++i) {
G4PhysicsLogVector* pv0 = static_cast<G4PhysicsLogVector*>((*(list[0]))[i]);
auto pv0 = static_cast<G4PhysicsLogVector*>((*(list[0]))[i]);
if(pv0 == nullptr) { continue; }
size_t npoints = pv0->GetVectorLength();
G4PhysicsLogVector* pv = new G4PhysicsLogVector(*pv0);
auto pv = new G4PhysicsLogVector(*pv0);
for (size_t j=0; j<npoints; ++j) {
G4double dedx = 0.0;
for (size_t k=0; k<n_processes; ++k) {
@@ -193,7 +193,7 @@ void G4LossTableBuilder::BuildRangeTable(const G4PhysicsTable* dedxTable,
const G4double del = 1.0/(G4double)n;
for (std::size_t i=0; i<nCouples; ++i) {
G4PhysicsLogVector* pv = static_cast<G4PhysicsLogVector*>((*dedxTable)[i]);
auto pv = static_cast<G4PhysicsLogVector*>((*dedxTable)[i]);
if((pv == nullptr) || (isBaseMatActive && !(*theFlag)[i])) { continue; }
std::size_t npoints = pv->GetVectorLength();
std::size_t bin0 = 0;
@@ -273,7 +273,7 @@ G4LossTableBuilder::BuildInverseRangeTable(const G4PhysicsTable* rangeTable,
std::size_t npoints = pv->GetVectorLength();
delete (*invRangeTable)[i];
G4PhysicsFreeVector* v = new G4PhysicsFreeVector(npoints,splineFlag);
auto v = new G4PhysicsFreeVector(npoints,splineFlag);
for (std::size_t j=0; j<npoints; ++j) {
G4double e = pv->Energy(j);
@@ -772,10 +772,6 @@ void G4LossTableManager::CopyTables(const G4ParticleDefinition* part,
<< G4endl;
}
}
if (theElectron == part && theElectron == proc->SecondaryParticle() ) {
proc->SetSecondaryRangeTable(base_proc->RangeTableForLoss());
}
}
}
@@ -809,7 +805,7 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
// possible case of process sharing between particle/anti-particle
if(!yes) {
G4VProcess* ptr = static_cast<G4VProcess*>(p);
auto ptr = static_cast<G4VProcess*>(p);
for(G4int j=0; j<nvec; ++j) {
//G4cout << "j= " << j << " " << (*pvec)[j] << " " << ptr << G4endl;
if(ptr == (*pvec)[j]) {
@@ -847,7 +843,7 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
if (0 == n_dedx || !em) {
G4cout << "G4LossTableManager WARNING: no DEDX processes for "
<< aParticle->GetParticleName() << G4endl;
return 0;
return nullptr;
}
G4int nSubRegions = em->NumberOfSubCutoffRegions();
@@ -870,7 +866,7 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
em->SetDEDXTable(dedx, fIsIonisation);
if (1 < n_dedx) {
dedx = 0;
dedx = nullptr;
dedx = G4PhysicsTableHelper::PreparePhysicsTable(dedx);
tableBuilder->BuildDEDXTable(dedx, t_list);
em->SetDEDXTable(dedx, fRestricted);
@@ -69,11 +69,6 @@ G4NIELCalculator::G4NIELCalculator(G4VEmModel* mod, G4int verb)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4NIELCalculator::~G4NIELCalculator()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4NIELCalculator::AddEmModel(G4VEmModel* mod)
{
if(mod && mod != fModel) {
@@ -86,7 +86,7 @@ G4OpticalParametersMessenger::G4OpticalParametersMessenger(
new G4UIcommand("/process/optical/processActivation", this);
fActivateProcessCmd->SetGuidance(
"Activate/deactivate the specified optical process");
G4UIparameter* par = new G4UIparameter("proc_name", 's', false);
auto par = new G4UIparameter("proc_name", 's', false);
G4String candidates;
for(G4int i = 0; i < kNoProcess; ++i)
{
@@ -0,0 +1,461 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4TransportationWithMsc
//
// Class Description:
//
// It is a generic process of transportation with multiple scattering included
// in the step limitation and propagation.
//
// Original author: Jonas Hahnfeld, 2022
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4TransportationWithMsc.hh"
#include "G4LossTableBuilder.hh"
#include "G4LossTableManager.hh"
#include "G4EmConfigurator.hh"
#include "G4VMscModel.hh"
#include "G4DynamicParticle.hh"
#include "G4Step.hh"
#include "G4StepPoint.hh"
#include "G4StepStatus.hh"
#include "G4Track.hh"
#include "G4Electron.hh"
#include "G4PhysicalConstants.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
static constexpr G4double kLowestKinEnergy = 10 * CLHEP::eV;
static constexpr G4double kGeomMin = 0.05 * CLHEP::nm;
static constexpr G4double kMinDisplacement2 = kGeomMin * kGeomMin;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4TransportationWithMsc::G4TransportationWithMsc(ScatteringType type,
G4int verbosity)
: G4Transportation(verbosity, "TransportationWithMsc")
, fType(type)
{
SetVerboseLevel(1);
fEmManager = G4LossTableManager::Instance();
fModelManager = new G4EmModelManager;
G4ThreeVector zero;
fSubStepDynamicParticle =
new G4DynamicParticle(G4Electron::Definition(), zero);
fSubStepTrack = new G4Track(fSubStepDynamicParticle, 0, zero);
fSubStep = new G4Step;
fSubStepTrack->SetStep(fSubStep);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4TransportationWithMsc::~G4TransportationWithMsc()
{
delete fModelManager;
// fSubStepDynamicParticle is owned and also deleted by fSubStepTrack!
delete fSubStepTrack;
delete fSubStep;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4TransportationWithMsc::AddMscModel(G4VMscModel* mscModel, G4int order,
const G4Region* region)
{
if(fType != ScatteringType::MultipleScattering)
{
G4Exception("G4TransportationWithMsc::AddMscModel", "em0051",
FatalException,
"not allowed unless type == MultipleScattering");
}
fModelManager->AddEmModel(order, mscModel, nullptr, region);
mscModel->SetParticleChange(&fParticleChange);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4TransportationWithMsc::PreparePhysicsTable(
const G4ParticleDefinition& part)
{
if(nullptr == fFirstParticle)
{
fFirstParticle = &part;
G4VMultipleScattering* ptr = nullptr;
auto emConfigurator = fEmManager->EmConfigurator();
emConfigurator->PrepareModels(&part, ptr, this);
}
if(fFirstParticle == &part)
{
G4bool master = fEmManager->IsMaster();
G4LossTableBuilder* bld = fEmManager->GetTableBuilder();
G4bool baseMat = bld->GetBaseMaterialFlag();
const auto* theParameters = G4EmParameters::Instance();
if(master)
{
SetVerboseLevel(theParameters->Verbose());
}
else
{
SetVerboseLevel(theParameters->WorkerVerbose());
}
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->SetMasterThread(master);
msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
G4double emax =
std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
msc->SetHighEnergyLimit(emax);
msc->SetUseBaseMaterials(baseMat);
}
fModelManager->Initialise(fFirstParticle, G4Electron::Electron(),
verboseLevel);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4TransportationWithMsc::BuildPhysicsTable(
const G4ParticleDefinition& part)
{
if(fFirstParticle == &part)
{
fEmManager->BuildPhysicsTable(fFirstParticle);
if(!fEmManager->IsMaster())
{
const auto masterProcess =
static_cast<const G4TransportationWithMsc*>(GetMasterProcess());
// Initialisation of models.
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
auto msc0 =
static_cast<G4VMscModel*>(masterProcess->fModelManager->GetModel(i));
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
msc->InitialiseLocal(fFirstParticle, msc0);
}
}
}
if(!G4EmParameters::Instance()->IsPrintLocked() && verboseLevel > 0)
{
G4cout << G4endl;
G4cout << GetProcessName() << ": for " << part.GetParticleName();
if(fMultipleSteps)
{
G4cout << " (multipleSteps: 1)";
}
G4cout << G4endl;
fModelManager->DumpModelList(G4cout, verboseLevel);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4TransportationWithMsc::StartTracking(G4Track* track)
{
auto* currParticle = track->GetParticleDefinition();
auto* ionisation = fEmManager->GetEnergyLossProcess(currParticle);
fSubStepDynamicParticle->SetDefinition(currParticle);
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->StartTracking(track);
msc->SetIonisation(ionisation, currParticle);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
const G4Track& track, G4double previousStepSize, G4double currentMinimumStep,
G4double& proposedSafety, G4GPILSelection* selection)
{
*selection = NotCandidateForSelection;
const G4double physStepLimit = currentMinimumStep;
switch(fType)
{
case ScatteringType::MultipleScattering: {
// Select the MSC model for the current kinetic energy.
G4VMscModel* mscModel = nullptr;
const G4double ekin = track.GetKineticEnergy();
const auto* couple = track.GetMaterialCutsCouple();
const auto* particleDefinition = track.GetParticleDefinition();
if(physStepLimit > kGeomMin)
{
G4double ekinForSelection = ekin;
G4double pdgMass = particleDefinition->GetPDGMass();
if(pdgMass > CLHEP::GeV)
{
ekinForSelection *= proton_mass_c2 / pdgMass;
}
if(ekinForSelection >= kLowestKinEnergy)
{
mscModel = static_cast<G4VMscModel*>(
fModelManager->SelectModel(ekinForSelection, couple->GetIndex()));
if(mscModel == nullptr)
{
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0052",
FatalException, "no MSC model found");
}
if(!mscModel->IsActive(ekinForSelection))
{
mscModel = nullptr;
}
}
}
// Call the MSC model to potentially limit the step and convert to
// geometric path length.
if(mscModel != nullptr)
{
mscModel->SetCurrentCouple(couple);
// Use the provided track for the first step.
const G4Track* currentTrackPtr = &track;
G4double currentSafety = proposedSafety;
G4double currentEnergy = ekin;
G4double stepLimitLeft = physStepLimit;
G4double totalGeometryStepLength = 0, totalTruePathLength = 0;
G4bool firstStep = true, continueStepping = fMultipleSteps;
do
{
G4double gPathLength = stepLimitLeft;
G4double tPathLength =
mscModel->ComputeTruePathLengthLimit(*currentTrackPtr, gPathLength);
G4bool mscLimitsStep = (tPathLength < stepLimitLeft);
if(!fMultipleSteps && mscLimitsStep)
{
// MSC limits the step.
*selection = CandidateForSelection;
}
if(!firstStep)
{
// Move the navigator to where the previous step ended.
fLinearNavigator->LocateGlobalPointWithinVolume(
fTransportEndPosition);
}
G4GPILSelection transportSelection;
G4double geometryStepLength =
G4Transportation::AlongStepGetPhysicalInteractionLength(
*currentTrackPtr, previousStepSize, gPathLength, currentSafety,
&transportSelection);
if(geometryStepLength < gPathLength)
{
// Transportation limits the step, ie the track hit a boundary.
*selection = CandidateForSelection;
continueStepping = false;
}
if(fTransportEndKineticEnergy != currentEnergy)
{
// Field propagation changed the energy, it's not possible to
// estimate the continuous energy loss and continue stepping.
continueStepping = false;
}
if(firstStep)
{
proposedSafety = currentSafety;
}
totalGeometryStepLength += geometryStepLength;
// Sample MSC direction change and displacement.
const G4double range =
mscModel->GetRange(particleDefinition, currentEnergy, couple);
tPathLength = mscModel->ComputeTrueStepLength(geometryStepLength);
// Protect against wrong t->g->t conversion.
tPathLength = std::min(tPathLength, stepLimitLeft);
totalTruePathLength += tPathLength;
if(*selection != CandidateForSelection && !mscLimitsStep)
{
// If neither MSC nor transportation limits the step, we got the
// distance we want - make sure we exit the loop.
continueStepping = false;
}
else if(tPathLength >= range)
{
// The particle will stop, exit the loop.
continueStepping = false;
}
else
{
stepLimitLeft -= tPathLength;
}
// Do not sample scattering at the last or at a small step.
if(tPathLength < range && tPathLength > kGeomMin)
{
static constexpr G4double minSafety = 1.20 * CLHEP::nm;
static constexpr G4double sFact = 0.99;
// The call to SampleScattering() *may* directly fill in the changed
// direction into fParticleChange, so we have to:
// 1) Make sure the momentum direction is initialized.
fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir);
// 2) Call SampleScattering(), which *may* change it.
const G4ThreeVector displacement =
mscModel->SampleScattering(fTransportEndMomentumDir, minSafety);
// 3) Get the changed direction and inform G4Transportation.
fMomentumChanged = true;
fTransportEndMomentumDir = *fParticleChange.GetMomentumDirection();
const G4double r2 = displacement.mag2();
if(r2 > kMinDisplacement2)
{
G4bool positionChanged = true;
G4double dispR = std::sqrt(r2);
G4double postSafety = sFact * fpSafetyHelper->ComputeSafety(
fTransportEndPosition, dispR);
// Far away from geometry boundary
if(postSafety > 0.0 && dispR <= postSafety)
{
fTransportEndPosition += displacement;
// Near the boundary
}
else
{
// displaced point is definitely within the volume
if(dispR < postSafety)
{
fTransportEndPosition += displacement;
// reduced displacement
}
else if(postSafety > kGeomMin)
{
fTransportEndPosition += displacement * (postSafety / dispR);
// very small postSafety
}
else
{
positionChanged = false;
}
}
if(positionChanged)
{
fpSafetyHelper->ReLocateWithinVolume(fTransportEndPosition);
}
}
}
if(continueStepping)
{
// Update safety according to the geometry distance.
if(currentSafety < fEndPointDistance)
{
currentSafety = 0;
}
else
{
currentSafety -= fEndPointDistance;
}
// Update the kinetic energy according to the continuous loss.
currentEnergy = mscModel->GetEnergy(particleDefinition,
range - tPathLength, couple);
// From now on, use the track that we can update below.
currentTrackPtr = fSubStepTrack;
fSubStepDynamicParticle->SetKineticEnergy(currentEnergy);
fSubStepDynamicParticle->SetMomentumDirection(
fTransportEndMomentumDir);
fSubStepTrack->SetPosition(fTransportEndPosition);
G4StepPoint& subPreStepPoint = *fSubStep->GetPreStepPoint();
subPreStepPoint.SetMaterialCutsCouple(couple);
subPreStepPoint.SetPosition(fTransportEndPosition);
subPreStepPoint.SetSafety(currentSafety);
subPreStepPoint.SetStepStatus(fAlongStepDoItProc);
}
firstStep = false;
} while(continueStepping);
// Note: currentEnergy is only updated if continueStepping is true.
// In case field propagation changed the energy, this flag is
// immediately set to false and currentEnergy is still equal to the
// initial kinetic energy stored in ekin.
if(currentEnergy != ekin)
{
// If field propagation didn't change the energy and we potentially
// did multiple steps, reset the energy that G4Transportation will
// propose to not subtract the energy loss twice.
fTransportEndKineticEnergy = ekin;
// Also ask for the range again with the initial energy so it is
// correctly cached in the G4VEnergyLossProcess.
// FIXME: Asking for a range should never change the cached values!
(void) mscModel->GetRange(particleDefinition, ekin, couple);
}
fParticleChange.ProposeTrueStepLength(totalTruePathLength);
return totalGeometryStepLength;
}
}
}
// If we get here, no scattering has happened.
return G4Transportation::AlongStepGetPhysicalInteractionLength(
track, previousStepSize, currentMinimumStep, proposedSafety, selection);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -79,8 +79,7 @@ G4VAtomDeexcitation::G4VAtomDeexcitation(const G4String& modname)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VAtomDeexcitation::~G4VAtomDeexcitation()
{}
G4VAtomDeexcitation::~G4VAtomDeexcitation() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -306,7 +305,7 @@ G4VAtomDeexcitation::AlongStepDeexcitation(std::vector<G4Track*>& tracks,
G4double rho = truelength*theAtomNumDensityVector[i];
//G4cout<<" Z "<< Z <<" is active x(mm)= " << truelength/mm << G4endl;
for(G4int ii=0; ii<nshells; ++ii) {
G4AtomicShellEnumerator as = G4AtomicShellEnumerator(ii);
auto as = (G4AtomicShellEnumerator)(ii);
const G4AtomicShell* shell = GetAtomicShell(Z, as);
const G4double bindingEnergy = shell->BindingEnergy();
@@ -61,8 +61,7 @@ G4VEmAngularDistribution::G4VEmAngularDistribution(const G4String& name)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmAngularDistribution::~G4VEmAngularDistribution()
{}
G4VEmAngularDistribution::~G4VEmAngularDistribution() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -56,6 +56,7 @@
#include "G4ParticleChangeForGamma.hh"
#include "G4EmParameters.hh"
#include "G4SystemOfUnits.hh"
#include "G4EmUtility.hh"
#include "G4Log.hh"
#include "Randomize.hh"
#include <iostream>
@@ -138,65 +139,8 @@ G4ParticleChangeForGamma* G4VEmModel::GetParticleChangeForGamma()
void G4VEmModel::InitialiseElementSelectors(const G4ParticleDefinition* part,
const G4DataVector& cuts)
{
// using spline for element selectors should be investigated in details
// because small number of points may provide biased results
// large number of points requires significant increase of memory
G4bool spline = false;
//G4cout << "IES: for " << GetName() << " Emin(MeV)= " << lowLimit/MeV
// << " Emax(MeV)= " << highLimit/MeV << G4endl;
// two times less bins because probability functon is normalized
// so correspondingly is more smooth
if(highLimit <= lowLimit) { return; }
G4int nbinsPerDec = G4EmParameters::Instance()->NumberOfBinsPerDecade();
G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
G4int numOfCouples = theCoupleTable->GetTableSize();
// prepare vector
if(!elmSelectors) {
elmSelectors = new std::vector<G4EmElementSelector*>;
}
if(numOfCouples > nSelectors) {
for(G4int i=nSelectors; i<numOfCouples; ++i) {
elmSelectors->push_back(nullptr);
}
nSelectors = numOfCouples;
}
// initialise vector
for(G4int i=0; i<numOfCouples; ++i) {
// no need in element selectors for infinite cuts
if(cuts[i] == DBL_MAX) { continue; }
auto couple = theCoupleTable->GetMaterialCutsCouple(i);
auto material = couple->GetMaterial();
SetCurrentCouple(couple);
// selector already exist then delete
delete (*elmSelectors)[i];
G4double emin = std::max(lowLimit, MinPrimaryEnergy(material, part, cuts[i]));
G4double emax = std::max(highLimit, 10*emin);
static const G4double invlog106 = 1.0/(6*G4Log(10.));
G4int nbins = (G4int)(nbinsPerDec*G4Log(emax/emin)*invlog106);
nbins = std::max(nbins, 3);
(*elmSelectors)[i] = new G4EmElementSelector(this,material,nbins,
emin,emax,spline);
((*elmSelectors)[i])->Initialise(part, cuts[i]);
/*
G4cout << "G4VEmModel::InitialiseElmSelectors i= " << i
<< " " << part->GetParticleName()
<< " for " << GetName() << " cut= " << cuts[i]
<< " " << (*elmSelectors)[i] << G4endl;
((*elmSelectors)[i])->Dump(part);
*/
}
G4EmUtility::InitialiseElementSelectors(this,part,cuts,lowLimit,highLimit);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -292,48 +236,47 @@ const G4Element* G4VEmModel::SelectRandomAtom(const G4Material* mat,
}
return fCurrentElement;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4VEmModel::SelectRandomAtomNumber(const G4Material* mat)
const G4Element* G4VEmModel::GetCurrentElement(const G4Material* mat) const
{
// this algorith assumes that cross section is proportional to
// number electrons multiplied by number of atoms
const size_t nn = mat->GetNumberOfElements();
fCurrentElement = mat->GetElement(0);
if(1 < nn) {
const G4double* at = mat->GetVecNbOfAtomsPerVolume();
G4double tot = mat->GetTotNbOfAtomsPerVolume()*G4UniformRand();
for(size_t i=0; i<nn; ++i) {
tot -= at[i];
if(tot <= 0.0) {
fCurrentElement = mat->GetElement(i);
break;
}
}
const G4Element* elm = fCurrentElement;
if(nullptr == elm && nullptr != mat) {
elm = G4EmUtility::SampleRandomElement(mat);
}
return fCurrentElement->GetZasInt();
return elm;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4VEmModel::SelectIsotopeNumber(const G4Element* elm)
G4int G4VEmModel::SelectRandomAtomNumber(const G4Material* mat) const
{
SetCurrentElement(elm);
const size_t ni = elm->GetNumberOfIsotopes();
fCurrentIsotope = elm->GetIsotope(0);
size_t idx = 0;
if(ni > 1) {
const G4double* ab = elm->GetRelativeAbundanceVector();
G4double x = G4UniformRand();
for(; idx<ni; ++idx) {
x -= ab[idx];
if (x <= 0.0) {
fCurrentIsotope = elm->GetIsotope(idx);
break;
}
}
const G4Element* elm = GetCurrentElement(mat);
return (nullptr == elm) ? 0 : elm->GetZasInt();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Isotope* G4VEmModel::GetCurrentIsotope(const G4Element* elm) const
{
const G4Isotope* iso = nullptr;
const G4Element* el = elm;
if(nullptr == el && nullptr != fCurrentCouple) {
el = GetCurrentElement(fCurrentCouple->GetMaterial());
}
return fCurrentIsotope->GetN();
if(nullptr != el) {
iso = G4EmUtility::SampleRandomIsotope(el);
}
return iso;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4VEmModel::SelectIsotopeNumber(const G4Element* elm) const
{
auto iso = GetCurrentIsotope(elm);
return (nullptr != iso) ? iso->GetN() : 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -58,7 +58,6 @@
#include "G4EmDataHandler.hh"
#include "G4PhysicsLogVector.hh"
#include "G4VParticleChange.hh"
#include "G4PhysicsModelCatalog.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4Gamma.hh"
@@ -68,7 +67,8 @@
#include "G4EmBiasingManager.hh"
#include "G4EmParameters.hh"
#include "G4EmProcessSubType.hh"
#include "G4LowEnergyEmProcessSubType.hh"
#include "G4EmTableUtil.hh"
#include "G4EmUtility.hh"
#include "G4DNAModelSubType.hh"
#include "G4GenericIon.hh"
#include "G4Log.hh"
@@ -87,12 +87,12 @@ G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type):
maxKinEnergy = 100.0*CLHEP::TeV;
// default lambda factor
logLambdaFactor = G4Log(lambdaFactor);
invLambdaFactor = 1.0/lambdaFactor;
// particle types
theGamma = G4Gamma::Gamma();
theElectron = G4Electron::Electron();
thePositron = G4Positron::Positron();
theGamma = G4Gamma::Gamma();
theElectron = G4Electron::Electron();
thePositron = G4Positron::Positron();
pParticleChange = &fParticleChange;
fParticleChange.SetSecondaryWeightByProcess(true);
@@ -101,6 +101,7 @@ G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type):
modelManager = new G4EmModelManager();
lManager = G4LossTableManager::Instance();
lManager->Register(this);
isTheMaster = lManager->IsMaster();
G4LossTableBuilder* bld = lManager->GetTableBuilder();
theDensityFactor = bld->GetDensityFactors();
theDensityIdx = bld->GetCoupleIndexes();
@@ -110,12 +111,6 @@ G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type):
G4VEmProcess::~G4VEmProcess()
{
/*
if(1 < verboseLevel) {
G4cout << "G4VEmProcess destruct " << GetProcessName()
<< " " << this << " " << theLambdaTable <<G4endl;
}
*/
if(isTheMaster) {
delete theData;
delete theEnergyOfCrossSectionMax;
@@ -127,22 +122,6 @@ G4VEmProcess::~G4VEmProcess()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::Clear()
{
currentCouple = nullptr;
preStepLambda = 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::MinPrimaryEnergy(const G4ParticleDefinition*,
const G4Material*)
{
return 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::AddEmModel(G4int order, G4VEmModel* ptr,
const G4Region* region)
{
@@ -165,16 +144,8 @@ void G4VEmProcess::SetEmModel(G4VEmModel* ptr, G4int)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmModel* G4VEmProcess::GetModelByIndex(G4int idx, G4bool ver) const
{
return modelManager->GetModel(idx, ver);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::PreparePhysicsTable(const G4ParticleDefinition& part)
{
isTheMaster = lManager->IsMaster();
if(nullptr == particle) { SetParticle(&part); }
if(part.GetParticleType() == "nucleus" &&
@@ -182,124 +153,75 @@ void G4VEmProcess::PreparePhysicsTable(const G4ParticleDefinition& part)
G4String pname = part.GetParticleName();
if(pname != "deuteron" && pname != "triton" &&
pname != "alpha" && pname != "He3" &&
pname != "alpha+" && pname != "helium" &&
pname != "hydrogen") {
pname != "alpha" && pname != "alpha+" &&
pname != "helium" && pname != "hydrogen") {
particle = G4GenericIon::GenericIon();
isIon = true;
}
}
if(1 < verboseLevel) {
G4cout << "G4VEmProcess::PreparePhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< " local particle " << particle->GetParticleName()
<< G4endl;
}
if(particle != &part) { return; }
lManager->PreparePhysicsTable(&part, this, isTheMaster);
Clear();
// for new run
currentCouple = nullptr;
preStepLambda = 0.0;
fLambdaEnergy = 0.0;
InitialiseProcess(particle);
G4LossTableBuilder* bld = lManager->GetTableBuilder();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
theCutsGamma = theCoupleTable->GetEnergyCutsVector(idxG4GammaCut);
theCutsElectron = theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut);
theCutsPositron = theCoupleTable->GetEnergyCutsVector(idxG4PositronCut);
// initialisation of the process
if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); }
if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); }
if(isTheMaster) {
SetVerboseLevel(theParameters->Verbose());
if(nullptr == theData) { theData = new G4EmDataHandler(2); }
if(fEmOnePeak == fXSType) {
if(nullptr == theEnergyOfCrossSectionMax) {
theEnergyOfCrossSectionMax = new std::vector<G4double>;
}
size_t n = theCoupleTable->GetTableSize();
theEnergyOfCrossSectionMax->resize(n, DBL_MAX);
}
} else {
SetVerboseLevel(theParameters->WorkerVerbose());
}
applyCuts = theParameters->ApplyCuts();
lambdaFactor = theParameters->LambdaFactor();
logLambdaFactor = G4Log(lambdaFactor);
invLambdaFactor = 1.0/lambdaFactor;
theParameters->DefineRegParamForEM(this);
// integral option may be disabled
if(!theParameters->Integral()) { fXSType = fEmNoIntegral; }
// prepare tables
if(buildLambdaTable && isTheMaster){
theLambdaTable = theData->MakeTable(0);
bld->InitialiseBaseMaterials(theLambdaTable);
}
// high energy table
if(isTheMaster && minKinEnergyPrim < maxKinEnergy){
theLambdaTablePrim = theData->MakeTable(1);
bld->InitialiseBaseMaterials(theLambdaTablePrim);
}
baseMat = bld->GetBaseMaterialFlag();
if(isTheMaster) {
if(nullptr == theData) { theData = new G4EmDataHandler(2); }
// initialisation of models
numberOfModels = modelManager->NumberOfModels();
for(G4int i=0; i<numberOfModels; ++i) {
G4VEmModel* mod = modelManager->GetModel(i);
if(nullptr == mod) { continue; }
if(nullptr == currentModel) { currentModel = mod; }
mod->SetPolarAngleLimit(theParameters->MscThetaLimit());
mod->SetMasterThread(isTheMaster);
if(mod->HighEnergyLimit() > maxKinEnergy) {
mod->SetHighEnergyLimit(maxKinEnergy);
if(buildLambdaTable) {
theLambdaTable = theData->MakeTable(0);
bld->InitialiseBaseMaterials(theLambdaTable);
}
// high energy table
if(minKinEnergyPrim < maxKinEnergy) {
theLambdaTablePrim = theData->MakeTable(1);
bld->InitialiseBaseMaterials(theLambdaTablePrim);
}
SetEmModel(mod);
mod->SetUseBaseMaterials(baseMat);
}
// models
baseMat = bld->GetBaseMaterialFlag();
numberOfModels = modelManager->NumberOfModels();
currentModel = modelManager->GetModel(0);
if(nullptr != lManager->AtomDeexcitation()) {
modelManager->SetFluoFlag(true);
}
fLambdaEnergy = 0.0;
theCuts =
modelManager->Initialise(particle,secondaryParticle,1.0,verboseLevel);
theCutsGamma = theCoupleTable->GetEnergyCutsVector(idxG4GammaCut);
theCutsElectron = theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut);
theCutsPositron = theCoupleTable->GetEnergyCutsVector(idxG4PositronCut);
// forced biasing
if(biasManager) {
biasManager->Initialise(part,GetProcessName(),verboseLevel);
if(nullptr != biasManager) {
biasManager->Initialise(part, GetProcessName(), verboseLevel);
biasFlag = false;
}
// defined ID of secondary particles
G4int stype = GetProcessSubType();
if(stype == fAnnihilation) {
secID = _Annihilation;
tripletID = _TripletGamma;
} else if(stype == fGammaConversion) {
secID = _PairProduction;
mainSecondaries = 2;
} else if(stype == fPhotoElectricEffect) {
secID = _PhotoElectron;
} else if(stype == fComptonScattering) {
secID = _ComptonElectron;
} else if(stype >= fLowEnergyElastic) {
secID = fDNAUnknownModel;
}
if(1 < verboseLevel) {
G4cout << "### G4VEmProcess::PreparePhysicsTable() done for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< " baseMat=" << baseMat << G4endl;
}
theCuts =
G4EmTableUtil::PrepareEmProcess(this, particle, secondaryParticle,
modelManager, maxKinEnergy,
secID, tripletID, mainSecondaries,
verboseLevel, isTheMaster);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -310,166 +232,31 @@ void G4VEmProcess::BuildPhysicsTable(const G4ParticleDefinition& part)
if(isTheMaster) { masterProc = this; }
else { masterProc = static_cast<const G4VEmProcess*>(GetMasterProcess());}
}
G4int nModels = modelManager->NumberOfModels();
G4bool isLocked = theParameters->IsPrintLocked();
G4bool toBuild = (buildLambdaTable || minKinEnergyPrim < maxKinEnergy);
G4String num = part.GetParticleName();
if(1 < verboseLevel) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << num
<< " buildLambdaTable= " << buildLambdaTable
<< " isTheMaster= " << isTheMaster
<< " " << masterProc
<< G4endl;
}
if(particle == &part) {
// worker initialisation
if(!isTheMaster) {
theLambdaTable = masterProc->LambdaTable();
theLambdaTablePrim = masterProc->LambdaTablePrim();
if(fXSType == fEmOnePeak) {
SetEnergyOfCrossSectionMax(masterProc->EnergyOfCrossSectionMax());
}
baseMat = masterProc->UseBaseMaterial();
// local initialisation of models
G4bool printing = true;
for(G4int i=0; i<numberOfModels; ++i) {
G4VEmModel* mod = GetModelByIndex(i, printing);
G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing);
//G4cout << i << ". " << mod << " " << mod0 << " "
// << particle->GetParticleName() << G4endl;
mod->SetUseBaseMaterials(baseMat);
mod->InitialiseLocal(particle, mod0);
}
// master thread
} else {
if(buildLambdaTable || minKinEnergyPrim < maxKinEnergy) {
BuildLambdaTable();
}
if(fXSType == fEmOnePeak) {
delete theEnergyOfCrossSectionMax;
theEnergyOfCrossSectionMax = nullptr;
SetEnergyOfCrossSectionMax(FindLambdaMax());
}
}
}
// protection against double printout
if(theParameters->IsPrintLocked()) { return; }
// explicitly defined printout by particle name
if(1 < verboseLevel ||
(0 < verboseLevel && (num == "gamma" || num == "e-" ||
num == "e+" || num == "mu+" ||
num == "mu-" || num == "proton"||
num == "pi+" || num == "pi-" ||
num == "kaon+" || num == "kaon-" ||
num == "alpha" || num == "anti_proton" ||
num == "GenericIon"|| num == "alpha++" ||
num == "alpha+" || num == "helium" ||
num == "hydrogen")))
{
StreamInfo(G4cout, part);
}
if(1 < verboseLevel) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() done for "
<< GetProcessName()
<< " and particle " << num
<< " baseMat=" << baseMat
<< G4endl;
}
G4EmTableUtil::BuildEmProcess(this, masterProc, particle, &part,
nModels, verboseLevel, isTheMaster,
isLocked, toBuild, baseMat);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::BuildLambdaTable()
{
if(1 < verboseLevel) {
G4cout << "G4EmProcess::BuildLambdaTable() for process "
<< GetProcessName() << " and particle "
<< particle->GetParticleName() << " " << this
<< G4endl;
}
// Access to materials
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4LossTableBuilder* bld = lManager->GetTableBuilder();
G4PhysicsLogVector* aVector = nullptr;
G4PhysicsLogVector* aVectorPrim = nullptr;
G4PhysicsLogVector* bVectorPrim = nullptr;
G4double scale = theParameters->MaxKinEnergy()/theParameters->MinKinEnergy();
G4int nbin =
theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale));
scale = G4Log(scale);
if(actBinning) { nbin = std::max(nbin, nLambdaBins); }
G4double emax1 = std::min(maxKinEnergy, minKinEnergyPrim);
for(size_t i=0; i<numOfCouples; ++i) {
if (bld->GetFlag(i)) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
// build main table
if(buildLambdaTable) {
delete (*theLambdaTable)[i];
// if start from zero then change the scale
G4double emin = minKinEnergy;
G4bool startNull = false;
if(startFromNull) {
G4double e = MinPrimaryEnergy(particle,couple->GetMaterial());
if(e >= emin) {
emin = e;
startNull = true;
}
}
G4double emax = emax1;
if(emax <= emin) { emax = 2*emin; }
G4int bin = G4lrint(nbin*G4Log(emax/emin)/scale);
if(bin < 3) { bin = 3; }
aVector = new G4PhysicsLogVector(emin, emax, bin, splineFlag);
modelManager->FillLambdaVector(aVector, couple, startNull);
if(splineFlag) { aVector->FillSecondDerivatives(); }
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector);
}
// build high energy table
if(minKinEnergyPrim < maxKinEnergy) {
delete (*theLambdaTablePrim)[i];
// start not from zero and always use spline
if(!bVectorPrim) {
G4int bin = G4lrint(nbin*G4Log(maxKinEnergy/minKinEnergyPrim)/scale);
if(bin < 3) { bin = 3; }
aVectorPrim =
new G4PhysicsLogVector(minKinEnergyPrim, maxKinEnergy, bin, true);
bVectorPrim = aVectorPrim;
} else {
aVectorPrim = new G4PhysicsLogVector(*bVectorPrim);
}
modelManager->FillLambdaVector(aVectorPrim, couple, false,
fIsCrossSectionPrim);
aVectorPrim->FillSecondDerivatives();
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTablePrim, i,
aVectorPrim);
}
}
}
if(1 < verboseLevel) {
G4cout << "Lambda table is built for "
<< particle->GetParticleName()
<< G4endl;
}
scale = nbin/G4Log(scale);
G4LossTableBuilder* bld = lManager->GetTableBuilder();
G4EmTableUtil::BuildLambdaTable(this, particle, modelManager,
bld, theLambdaTable, theLambdaTablePrim,
minKinEnergy, minKinEnergyPrim,
maxKinEnergy, scale, verboseLevel,
startFromNull, splineFlag);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -490,10 +277,8 @@ void G4VEmProcess::StreamInfo(std::ostream& out,
out << " BuildTable=" << buildLambdaTable << G4endl;
if(buildLambdaTable) {
if(particle == &part) {
size_t length = theLambdaTable->length();
for(size_t i=0; i<length; ++i) {
G4PhysicsVector* v = (*theLambdaTable)[i];
if(v) {
for(auto & v : *theLambdaTable) {
if(nullptr != v) {
out << " Lambda table from ";
G4double emin = v->Energy(0);
G4double emax = v->GetMaxEnergy();
@@ -514,11 +299,9 @@ void G4VEmProcess::StreamInfo(std::ostream& out,
}
}
if(minKinEnergyPrim < maxKinEnergy) {
if(particle == &part) {
size_t length = theLambdaTablePrim->length();
for(size_t i=0; i<length; ++i) {
G4PhysicsVector* v = (*theLambdaTablePrim)[i];
if(v) {
if(particle == &part) {
for(auto & v : *theLambdaTablePrim) {
if(nullptr != v) {
out << " LambdaPrime table from "
<< G4BestUnit(v->Energy(0),"Energy")
<< " to "
@@ -617,7 +400,7 @@ G4double G4VEmProcess::PostStepGetPhysicalInteractionLength(
theNumberOfInteractionLengthLeft = -G4Log( G4UniformRand() );
theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
} else if(currentInteractionLength < DBL_MAX) {
} else {
theNumberOfInteractionLengthLeft -=
previousStepSize/currentInteractionLength;
@@ -640,7 +423,7 @@ void G4VEmProcess::ComputeIntegralLambda(G4double e, G4double loge)
preStepLambda = GetCurrentLambda(e, loge);
} else if(fXSType == fEmIncreasing) {
if(e/lambdaFactor < mfpKinEnergy) {
if(e*invLambdaFactor < mfpKinEnergy) {
mfpKinEnergy = e;
preStepLambda = GetCurrentLambda(e, loge);
}
@@ -655,7 +438,7 @@ void G4VEmProcess::ComputeIntegralLambda(G4double e, G4double loge)
} else if(fXSType == fEmOnePeak) {
const G4double epeak = (*theEnergyOfCrossSectionMax)[currentCoupleIndex];
if(e <= epeak) {
if(e/lambdaFactor < mfpKinEnergy) {
if(e*invLambdaFactor < mfpKinEnergy) {
mfpKinEnergy = e;
preStepLambda = GetCurrentLambda(e, loge);
}
@@ -675,7 +458,7 @@ void G4VEmProcess::ComputeIntegralLambda(G4double e, G4double loge)
G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
// In all cases clear number of interaction lengths
// clear number of interaction lengths in any case
theNumberOfInteractionLengthLeft = -1.0;
mfpKinEnergy = DBL_MAX;
@@ -685,7 +468,7 @@ G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
// should be performed by the AtRestDoIt!
if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; }
const G4double finalT = track.GetKineticEnergy();
const G4double finalT = track.GetKineticEnergy();
// forced process - should happen only once per track
if(biasFlag) {
@@ -701,23 +484,20 @@ G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
// Integral approach
if (fXSType != fEmNoIntegral) {
const G4double logFinalT = track.GetDynamicParticle()->GetLogKineticEnergy();
const G4double logFinalT =
track.GetDynamicParticle()->GetLogKineticEnergy();
const G4double lx = std::max(GetCurrentLambda(finalT, logFinalT), 0.0);
const G4double lg = preStepLambda;
if(finalT < mfpKinEnergy) {
mfpKinEnergy = finalT;
preStepLambda = lx;
}
#ifdef G4VERBOSE
if(lg < lx && 1 < verboseLevel) {
if(preStepLambda < lx && 1 < verboseLevel) {
G4cout << "WARNING: for " << currentParticle->GetParticleName()
<< " and " << GetProcessName()
<< " E(MeV)= " << finalT/MeV
<< " preLambda= " << lg << " < " << lx << " (postLambda) "
<< G4endl;
<< " and " << GetProcessName() << " E(MeV)= " << finalT/MeV
<< " preLambda= " << preStepLambda
<< " < " << lx << " (postLambda) " << G4endl;
}
#endif
if(lg*G4UniformRand() >= lx) {
// if false interaction then use new cross section value
// if both values are zero - no interaction
if(preStepLambda*G4UniformRand() >= lx) {
return &fParticleChange;
}
}
@@ -860,127 +640,46 @@ G4bool G4VEmProcess::StorePhysicsTable(const G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
G4bool yes = true;
if(!isTheMaster) { return yes; }
if ( theLambdaTable && part == particle) {
const G4String& nam =
GetPhysicsTableFileName(part,directory,"Lambda",ascii);
yes = theLambdaTable->StorePhysicsTable(nam,ascii);
if ( yes ) {
if(0 < verboseLevel) G4cout << "Stored: " << nam << G4endl;
} else {
G4cout << "Fail to store Physics Table for "
<< particle->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
if(!isTheMaster || part != particle) { return true; }
if(G4EmTableUtil::StoreTable(this, part, theLambdaTable,
directory, "Lambda",
verboseLevel, ascii) &&
G4EmTableUtil::StoreTable(this, part, theLambdaTablePrim,
directory, "LambdaPrim",
verboseLevel, ascii)) {
return true;
}
if ( theLambdaTablePrim && part == particle) {
const G4String& name =
GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
yes = theLambdaTablePrim->StorePhysicsTable(name,ascii);
if ( yes ) {
if(0 < verboseLevel) {
G4cout << "Physics table prim is stored for "
<< particle->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
} else {
G4cout << "Fail to store Physics Table Prim for "
<< particle->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
}
return yes;
return false;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4bool G4VEmProcess::RetrievePhysicsTable(const G4ParticleDefinition* part,
const G4String& directory,
const G4String& dir,
G4bool ascii)
{
if(1 < verboseLevel) {
G4cout << "G4VEmProcess::RetrievePhysicsTable() for "
<< part->GetParticleName() << " and process "
<< GetProcessName() << G4endl;
}
if(!isTheMaster || part != particle) { return true; }
G4bool yes = true;
if((!buildLambdaTable && minKinEnergyPrim > maxKinEnergy)
|| particle != part) { return yes; }
const G4String particleName = part->GetParticleName();
if(buildLambdaTable) {
const G4String& filename =
GetPhysicsTableFileName(part,directory,"Lambda",ascii);
yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTable,
filename,ascii,
splineFlag);
if ( yes ) {
if (0 < verboseLevel) {
G4cout << "Lambda table for " << particleName
<< " is Retrieved from <"
<< filename << ">"
<< G4endl;
}
if(splineFlag) {
for(auto & v : *theLambdaTable) {
if(nullptr != v) { v->FillSecondDerivatives(); }
}
}
} else {
if (1 < verboseLevel) {
G4cout << "Lambda table for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
}
yes = G4EmTableUtil::RetrieveTable(this, part, theLambdaTable, dir,
"Lambda", verboseLevel,
ascii, splineFlag);
}
if(minKinEnergyPrim < maxKinEnergy) {
const G4String& filename =
GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii);
yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTablePrim,
filename,ascii,true);
if ( yes ) {
if (0 < verboseLevel) {
G4cout << "Lambda table prim for " << particleName
<< " is Retrieved from <"
<< filename << ">"
<< G4endl;
}
for(auto & v : *theLambdaTablePrim) {
if(nullptr != v) { v->FillSecondDerivatives(); }
}
} else {
if (1 < verboseLevel) {
G4cout << "Lambda table prim for " << particleName << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
}
if(yes && minKinEnergyPrim < maxKinEnergy) {
yes = G4EmTableUtil::RetrieveTable(this, part, theLambdaTablePrim, dir,
"LambdaPrim", verboseLevel,
ascii, splineFlag);
}
return yes;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::CrossSectionPerVolume(G4double kinEnergy,
const G4MaterialCutsCouple* couple,
G4double)
G4double G4VEmProcess::GetCrossSection(G4double kinEnergy,
const G4MaterialCutsCouple* couple)
{
G4double cross = RecalculateLambda(kinEnergy, couple);
return std::max(cross, 0.0);
CurrentSetup(couple, kinEnergy);
return GetCurrentLambda(kinEnergy, G4Log(kinEnergy));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -995,17 +694,6 @@ G4double G4VEmProcess::GetMeanFreePath(const G4Track& track,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::MeanFreePath(const G4Track& track)
{
const G4double kinEnergy = track.GetKineticEnergy();
CurrentSetup(track.GetMaterialCutsCouple(), kinEnergy);
const G4double xs = GetCurrentLambda(kinEnergy,
track.GetDynamicParticle()->GetLogKineticEnergy());
return (0.0 < xs) ? 1.0/xs : DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4VEmProcess::ComputeCrossSectionPerAtom(G4double kinEnergy,
G4double Z, G4double A, G4double cut)
@@ -1018,78 +706,6 @@ G4VEmProcess::ComputeCrossSectionPerAtom(G4double kinEnergy,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4double>* G4VEmProcess::FindLambdaMax()
{
if(1 < verboseLevel) {
G4cout << "### G4VEmProcess::FindLambdaMax: "
<< particle->GetParticleName()
<< " and process " << GetProcessName() << " " << G4endl;
}
std::vector<G4double>* ptr = nullptr;
if(fXSType != fEmOnePeak) { return ptr; }
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t n = theCoupleTable->GetTableSize();
ptr = new std::vector<G4double>;
ptr->resize(n, DBL_MAX);
G4bool isPeak = false;
const G4double g4log10 = G4Log(10.);
const G4double scale = theParameters->NumberOfBinsPerDecade()/g4log10;
for(size_t i=0; i<n; ++i) {
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
G4double emin = std::max(minKinEnergy, MinPrimaryEnergy(particle, couple->GetMaterial()));
G4double emax = std::max(maxKinEnergy, emin + emin);
G4double ee = G4Log(emax/emin);
G4int nbin = G4lrint(ee*scale);
if(nbin < 4) { nbin = 4; }
G4double x = G4Exp(ee/nbin);
G4double sm = 0.0;
G4double em = emin;
G4double e = emin;
for(G4int j=0; j<=nbin; ++j) {
G4double sig = RecalculateLambda(e, couple);
//G4cout << j << " E=" << e << " Lambda=" << sig << G4endl;
if(sig >= sm) {
em = e;
sm = sig;
e *= x;
} else {
isPeak = true;
(*ptr)[i] = em;
break;
}
}
if(1 < verboseLevel) {
G4cout << " " << i << ". Epeak(GeV)=" << em/GeV
<< " SigmaMax(1/mm)=" << sm
<< " Emin(GeV)=" << emin/GeV << " Emax(GeV)=" << emax/GeV
<< " " << couple->GetMaterial()->GetName() << G4endl;
}
}
// there is no peak for any material
if(!isPeak) {
delete ptr;
ptr = nullptr;
}
return ptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetEnergyOfCrossSectionMax(std::vector<G4double>* ptr)
{
if(nullptr == ptr) {
fXSType = fEmIncreasing;
} else {
theEnergyOfCrossSectionMax = ptr;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector*
G4VEmProcess::LambdaPhysicsVector(const G4MaterialCutsCouple* couple)
{
@@ -1103,7 +719,24 @@ G4VEmProcess::LambdaPhysicsVector(const G4MaterialCutsCouple* couple)
const G4Element* G4VEmProcess::GetCurrentElement() const
{
return (nullptr != currentModel) ? currentModel->GetCurrentElement() : nullptr;
return (nullptr != currentModel) ?
currentModel->GetCurrentElement(currentMaterial) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Element* G4VEmProcess::GetTargetElement() const
{
return (nullptr != currentModel) ?
currentModel->GetCurrentElement(currentMaterial) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Isotope* G4VEmProcess::GetTargetIsotope() const
{
return (nullptr != currentModel) ?
currentModel->GetCurrentIsotope(GetCurrentElement()) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1224,15 +857,6 @@ G4VEmProcess* G4VEmProcess::GetEmProcess(const G4String& nam)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4VEmProcess::GetLambda(G4double kinEnergy, const G4MaterialCutsCouple* couple)
{
CurrentSetup(couple, kinEnergy);
return GetCurrentLambda(kinEnergy, G4Log(kinEnergy));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::PolarAngleLimit() const
{
return theParameters->MscThetaLimit();
@@ -1256,7 +880,7 @@ void G4VEmProcess::PrintWarning(G4String tit, G4double val)
void G4VEmProcess::ProcessDescription(std::ostream& out) const
{
if(particle) {
if(nullptr != particle) {
StreamInfo(out, *particle, true);
}
}
File diff suppressed because it is too large Load Diff
@@ -69,8 +69,7 @@ G4VMscModel::G4VMscModel(const G4String& nam):
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VMscModel::~G4VMscModel()
{}
G4VMscModel::~G4VMscModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -78,6 +78,7 @@
#include "G4ProcessVector.hh"
#include "G4ProcessManager.hh"
#include "G4LossTableBuilder.hh"
#include "G4EmTableUtil.hh"
#include <iostream>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -93,7 +94,7 @@ G4VMultipleScattering::G4VMultipleScattering(const G4String&, G4ProcessType)
lowestKinEnergy = 10*CLHEP::eV;
geomMin = 0.05*CLHEP::nm;
geomMin = 0.05*CLHEP::nm;
minDisplacement2 = geomMin*geomMin;
pParticleChange = &fParticleChange;
@@ -114,7 +115,7 @@ G4VMultipleScattering::~G4VMultipleScattering()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* ptr,
void G4VMultipleScattering::AddEmModel(G4int order, G4VMscModel* ptr,
const G4Region* region)
{
if(nullptr == ptr) { return; }
@@ -139,76 +140,22 @@ void G4VMultipleScattering::SetEmModel(G4VMscModel* ptr, G4int)
void
G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part)
{
if(1 < verboseLevel) {
G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
G4bool master = emManager->IsMaster();
if(nullptr == firstParticle) { firstParticle = &part; }
if(part.GetPDGMass() > CLHEP::GeV) {
// flag declears that mass scaling is applied
isIon = true;
}
emManager->PreparePhysicsTable(&part, this, master);
currParticle = nullptr;
if(1 < verboseLevel) {
G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< " local particle " << firstParticle->GetParticleName()
<< " isIon: " << isIon << " isMaster: " << master
<< G4endl;
}
if(firstParticle == &part) {
baseMat = emManager->GetTableBuilder()->GetBaseMaterialFlag();
// initialise process
InitialiseProcess(firstParticle);
G4EmTableUtil::PrepareMscProcess(this, part, modelManager,
stepLimit, facrange,
latDisplacement, master,
isIon, baseMat);
// heavy particles
if(part.GetPDGMass() > CLHEP::MeV) {
stepLimit = theParameters->MscMuHadStepLimitType();
facrange = theParameters->MscMuHadRangeFactor();
latDisplacement = theParameters->MuHadLateralDisplacement();
} else {
stepLimit = theParameters->MscStepLimitType();
facrange = theParameters->MscRangeFactor();
latDisplacement = theParameters->LateralDisplacement();
}
if(master) { SetVerboseLevel(theParameters->Verbose()); }
else { SetVerboseLevel(theParameters->WorkerVerbose()); }
// initialisation of models
numberOfModels = modelManager->NumberOfModels();
/*
std::cout << "### G4VMultipleScattering::PreparePhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< " Nmodels= " << mscModels.size() << " " << this << std::endl;
*/
G4LossTableBuilder* bld = emManager->GetTableBuilder();
baseMat = bld->GetBaseMaterialFlag();
for(G4int i=0; i<numberOfModels; ++i) {
G4VMscModel* msc = GetModelByIndex(i);
if(nullptr == msc) { continue; }
if(nullptr == currentModel) { currentModel = msc; }
msc->SetIonisation(nullptr, firstParticle);
msc->SetMasterThread(master);
msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
G4double emax =
std::min(msc->HighEnergyLimit(),theParameters->MaxKinEnergy());
msc->SetHighEnergyLimit(emax);
msc->SetUseBaseMaterials(baseMat);
}
modelManager->Initialise(firstParticle, G4Electron::Electron(),
1.0, verboseLevel);
currentModel = GetModelByIndex(0);
if(nullptr == safetyHelper) {
safetyHelper = G4TransportationManager::GetTransportationManager()
@@ -222,66 +169,18 @@ G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part)
void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
{
const G4String& num = part.GetParticleName();
G4bool master = emManager->IsMaster();
if(1 < verboseLevel) {
G4cout << "### G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << num << " isIon: " << isIon
<< " IsMaster: " << master << G4endl;
}
const G4VMultipleScattering* masterProcess =
static_cast<const G4VMultipleScattering*>(GetMasterProcess());
if(firstParticle == &part) {
/*
std::cout << "### G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName() << " and particle " << num
<< " IsMaster= " << G4LossTableManager::Instance()->IsMaster()
<< " " << this << std::endl;
*/
emManager->BuildPhysicsTable(firstParticle);
if(!master) {
// initialisation of models
/*
std::cout << "### G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName() << " and particle " << num
<< " Nmod= " << mscModels.size() << " NOT master" << std::endl;
*/
baseMat = masterProcess->UseBaseMaterial();
for(G4int i=0; i<numberOfModels; ++i) {
G4VMscModel* msc = GetModelByIndex(i);
if(nullptr == msc) { continue; }
G4VMscModel* msc0 = masterProcess->GetModelByIndex(i);
msc->SetUseBaseMaterials(baseMat);
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
msc->InitialiseLocal(firstParticle, msc0);
}
}
}
// protection against double printout
if(theParameters->IsPrintLocked()) { return; }
// explicitly defined printout by particle name
if(1 < verboseLevel ||
(0 < verboseLevel && (num == "e-" ||
num == "e+" || num == "mu+" ||
num == "mu-" || num == "proton"||
num == "pi+" || num == "pi-" ||
num == "kaon+" || num == "kaon-" ||
num == "alpha" || num == "anti_proton" ||
num == "GenericIon" || num == "alpha+" ||
num == "alpha++" )))
{
StreamInfo(G4cout, part);
}
if(1 < verboseLevel) {
G4cout << "### G4VMultipleScattering::BuildPhysicsTable() done for "
<< GetProcessName()
<< " and particle " << num << G4endl;
const G4VMultipleScattering* ptr = this;
if(!master) {
ptr = static_cast<const G4VMultipleScattering*>(GetMasterProcess());
}
G4EmTableUtil::BuildMscProcess(this, ptr, part, firstParticle,
numberOfModels, master);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -306,22 +205,8 @@ void G4VMultipleScattering::StartTracking(G4Track* track)
fIonisation = emManager->GetEnergyLossProcess(currParticle);
eloss = fIonisation;
}
/*
G4cout << "G4VMultipleScattering::StartTracking Nmod= " << numberOfModels
<< " " << currParticle->GetParticleName()
<< " E(MeV)= " << track->GetKineticEnergy()
<< " Ion= " << fIonisation << " IsMaster= "
<< G4LossTableManager::Instance()->IsMaster()
<< G4endl;
*/
for(G4int i=0; i<numberOfModels; ++i) {
G4VMscModel* msc = GetModelByIndex(i);
/*
G4cout << "Next model " << msc
<< " Emin= " << msc->LowEnergyLimit()
<< " Emax= " << msc->HighEnergyLimit()
<< " Eact= " << msc->LowEnergyActivationLimit() << G4endl;
*/
msc->StartTracking(track);
if(nullptr != eloss) {
msc->SetIonisation(eloss, currParticle);
@@ -355,9 +240,10 @@ G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength(
}
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
// select new model
// select new model, static cast is possible in this class
if(1 < numberOfModels) {
currentModel = static_cast<G4VMscModel*>(SelectModel(ekin,couple->GetIndex()));
currentModel =
static_cast<G4VMscModel*>(SelectModel(ekin,couple->GetIndex()));
}
currentModel->SetCurrentCouple(couple);
// msc is active is model is active, energy above the limit,
@@ -371,7 +257,10 @@ G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength(
if (tPathLength < physStepLimit) {
*selection = CandidateForSelection;
}
} else { isActive = false; }
} else {
isActive = false;
gPathLength = DBL_MAX;
}
//if(currParticle->GetPDGMass() > GeV)
/*
@@ -537,41 +426,11 @@ G4VMultipleScattering::StorePhysicsTable(const G4ParticleDefinition* part,
G4bool ascii)
{
G4bool yes = true;
if(part != firstParticle) { return yes; }
const G4VMultipleScattering* masterProcess =
static_cast<const G4VMultipleScattering*>(GetMasterProcess());
if(nullptr != masterProcess && masterProcess != this) { return yes; }
if(part != firstParticle || !emManager->IsMaster()) { return yes; }
G4int nmod = modelManager->NumberOfModels();
static const G4String ss[4] = {"1","2","3","4"};
for(G4int i=0; i<nmod; ++i) {
G4VEmModel* msc = modelManager->GetModel(i);
if(nullptr == msc) { continue; }
yes = true;
G4PhysicsTable* table = msc->GetCrossSectionTable();
if (nullptr != table) {
G4int j = std::min(i,3);
G4String name =
GetPhysicsTableFileName(part,directory,"LambdaMod"+ss[j],ascii);
yes = table->StorePhysicsTable(name,ascii);
if ( yes ) {
if ( verboseLevel>0 ) {
G4cout << "Physics table are stored for "
<< part->GetParticleName()
<< " and process " << GetProcessName()
<< " with a name <" << name << "> " << G4endl;
}
} else {
G4cout << "Fail to store Physics Table for "
<< part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
}
}
return yes;
return G4EmTableUtil::StoreMscTable(this, part, directory,
numberOfModels, verboseLevel,
ascii);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -586,18 +445,9 @@ G4VMultipleScattering::RetrievePhysicsTable(const G4ParticleDefinition*,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::SetIonisation(G4VEnergyLossProcess* p)
{
for(auto & msc : mscModels) {
if(nullptr != msc) { msc->SetIonisation(p, firstParticle); }
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::ProcessDescription(std::ostream& outFile) const
{
if(firstParticle) {
if(nullptr != firstParticle) {
StreamInfo(outFile, *firstParticle, true);
}
}