Import Geant4 5.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 10:15:15 +02:00
parent 37fff30d2e
commit fbd4999cf7
4396 changed files with 56662 additions and 52446 deletions
+81 -1
View File
@@ -1,4 +1,4 @@
$Id: History,v 1.67 2002/12/13 11:15:01 gcosmo Exp $
$Id: History,v 1.93 2003/04/28 15:33:28 vnivanch Exp $
-------------------------------------------------------------------
=========================================================
@@ -17,6 +17,86 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
28 Apr 03: V.Ivant (utils-V05-00-13)
- add control on range for msc (effective for ions)
26 Apr 03: V.Ivant (utils-V05-00-12)
- fix of store/retrieve tables for msc and STD
- cleanup Bohr and Ion fluctuations
17 Apr 03: V.Ivant (utils-V05-00-11)
- additional clean up of msc variables
- improve output
13 Apr 03: V.Ivant (utils-V05-00-10)
- Add additional initialisation msc variables
- Add interface between standard and STD tables
09 Apr 03: V.Ivant (utils-V05-00-09)
- Fix problem of negative step limit for STD
07 Apr 03: V.Ivant (utils-V05-00-08)
- Add DeRegister to STD loss classes
- Add G4VMultipleScattering
- Remove STD messenger
26 Mar 03: V.Ivant (utils-V05-00-07)
- Add GetDEDXDispersion to STD loss tables
25 Mar 03: mma
- G4VEnergyLoss : add finalRangeRequested
12 Mar 03: V.Ivant (utils-V05-00-06)
- Add warning and G4Exception to G4EnergyLossTable
- Fix in MSC cut per region
- Fix in initialisation for STD
- Make messanger active at PreInit
10 Mar 03: V.Ivant (utils-V05-00-05)
- Updated MSC
- SubType for GenericIons
- Fix in energy range of models for STD
26 feb 03: V.Ivant (utils-V05-00-04a)
- For the February reference tag return back msc of 5.0
- Simplify control on GenericIons for STD
18 feb 03: V.Ivant (utils-V05-00-04)
- add control on CutsCouple usage
- utilise SubType for GenericIons
- fix problems with lambda and range tables for STD hadrons/ions
- fix problem of several runs with changed cuts/couples for STD
13 feb 03: V.Ivant
- add names for all models
- make the set of model per region available
- make SubCutoff regime available per region
10 feb 03: mma (utils-V05-00-03)
- tag to take account the Laszlo + Vladimir modifs
07 feb 03: V.Ivant
- fix problem in fluctuations for STD
06 feb 03: L.Urban
- important modifications in MSC (both in old design and model
version)
- changes in data members
- algorithm to reduce the step dependence is new
- new sampling for the geom.pathlengths
05 feb 03: V.Ivant (utils-V05-00-02)
- Fix on warnings at SUN for STD classes
- Add Initialise method to STD classes to calculate PartialSumSigma
- Subsitute Material by MaterialCutsCouple for PostStep STD
24 jan 03: V.Ivant (utils-V05-00-01)
- Migration to "cut per region"
06 jan 03: V.Ivant (utils-V05-00-00)
- Update interfaces to STD classes in order to be ready to migrade
to "cut per region"
12 dec 02: V.Ivant (utils-V04-01-12)
- Fix in multiple scattering for 1 MeV protons in both implementations.
@@ -29,13 +29,17 @@
// File name: G4BetheBlochModel
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// 23-12-02 V.Ivanchenko change interface in order to moveto cut per region
// 24-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
// Class Description:
//
// Implementation of Bethe-Bloch model of energy loss and
// delta-electron production by heavy charged particles
@@ -53,25 +57,24 @@ class G4BetheBlochModel : public G4VEmModel
public:
G4BetheBlochModel(const G4ParticleDefinition* p = 0);
G4BetheBlochModel(const G4ParticleDefinition* p = 0, const G4String& nam = "BetheBloch");
~G4BetheBlochModel();
G4double HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*);
G4double LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*);
void Initialise(const G4ParticleDefinition*, const G4DataVector&);
void SetHighEnergyLimit(const G4Material*, G4double e) {highKinEnergy = e;};
void SetLowEnergyLimit(const G4Material*, G4double e) {lowKinEnergy = e;};
G4double HighEnergyLimit(const G4ParticleDefinition* p);
G4double LowEnergyLimit(const G4ParticleDefinition* p);
void SetHighEnergyLimit(G4double e) {highKinEnergy = e;};
void SetLowEnergyLimit(G4double e) {lowKinEnergy = e;};
G4double MinEnergyCut(const G4ParticleDefinition*,
const G4Material*);
G4bool IsInCharge(const G4ParticleDefinition*,
const G4Material*);
const G4MaterialCutsCouple*);
G4bool IsInCharge(const G4ParticleDefinition*);
G4double ComputeDEDX(const G4Material*,
const G4ParticleDefinition*,
@@ -84,12 +87,28 @@ public:
G4double cutEnergy,
G4double maxEnergy);
G4std::vector<G4DynamicParticle*>* SampleSecondary(
const G4Material*,
G4DynamicParticle* SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy);
G4std::vector<G4DynamicParticle*>* SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy);
G4double SampleCosineTheta(G4double& kineticEnergy,
G4double& energyDeposition,
G4double& stepLength,
G4double& lambda) {return 1.0;};
G4double SampleDisplacement(G4double& kineticEnergy,
G4double& truePathLength,
G4double& stepLength,
G4double& lambda) {return 0.0;};
G4double MaxSecondaryEnergy(const G4DynamicParticle*);
protected:
@@ -0,0 +1,117 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
//
//
// File name: G4BohrFluctuations
//
// Author: Vladimir Ivanchenko
//
// Creation date: 02.04.2003
//
// Modifications:
//
//
// Class Description:
//
// Implementation of Gaussion energy loss Fluctuations
// -------------------------------------------------------------------
//
#ifndef G4BohrFluctuations_h
#define G4BohrFluctuations_h 1
#include "G4VEmFluctuationModel.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
class G4BohrFluctuations : public G4VEmFluctuationModel
{
public:
G4BohrFluctuations(const G4String& nam = "BohrFluc");
~G4BohrFluctuations();
G4double SampleFluctuations(const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&,
G4double&);
G4double Dispersion( const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&);
void Initialise(const G4ParticleDefinition*);
protected:
private:
// hide assignment operator
G4BohrFluctuations & operator=(const G4BohrFluctuations &right);
G4BohrFluctuations(const G4BohrFluctuations&);
const G4ParticleDefinition* particle;
G4double particleMass;
G4double chargeSquare;
G4double minNumberInteractionsBohr;
G4double minFraction;
// cash
G4double kineticEnergy;
G4double beta2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4BohrFluctuations::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
G4double electronDensity = material->GetElectronDensity();
kineticEnergy = dp->GetKineticEnergy();
G4double gam = kineticEnergy/particleMass + 1.0;
beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
return siga;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -29,13 +29,16 @@
// File name: G4BraggModel
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
// 23-12-02 V.Ivanchenko change interface in order to moveto cut per region
// 24-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
//
// Class Description:
// Class Description:
//
// Implementation of energy loss and delta-electron production
// by heavy slow charged particles using eveluated data
@@ -53,25 +56,24 @@ class G4BraggModel : public G4VEmModel
public:
G4BraggModel(const G4ParticleDefinition* p = 0);
G4BraggModel(const G4ParticleDefinition* p = 0, const G4String& nam = "Bragg");
~G4BraggModel();
G4double HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*);
G4double LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*);
void Initialise(const G4ParticleDefinition*, const G4DataVector&);
void SetHighEnergyLimit(const G4Material*, G4double e) {highKinEnergy = e;};
void SetLowEnergyLimit(const G4Material*, G4double e) {lowKinEnergy = e;};
G4double HighEnergyLimit(const G4ParticleDefinition*);
G4double LowEnergyLimit(const G4ParticleDefinition*);
void SetHighEnergyLimit(G4double e) {highKinEnergy = e;};
void SetLowEnergyLimit(G4double e) {lowKinEnergy = e;};
G4double MinEnergyCut(const G4ParticleDefinition*,
const G4Material*);
G4bool IsInCharge(const G4ParticleDefinition*,
const G4Material*);
const G4MaterialCutsCouple*);
G4bool IsInCharge(const G4ParticleDefinition*);
G4double ComputeDEDX(const G4Material*,
const G4ParticleDefinition*,
@@ -84,12 +86,28 @@ public:
G4double cutEnergy,
G4double maxEnergy);
G4std::vector<G4DynamicParticle*>* SampleSecondary(
const G4Material*,
G4DynamicParticle* SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy);
G4std::vector<G4DynamicParticle*>* SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy);
G4double SampleCosineTheta(G4double& kineticEnergy,
G4double& energyDeposition,
G4double& stepLength,
G4double& lambda) {return 1.0;};
G4double SampleDisplacement(G4double& kineticEnergy,
G4double& truePathLength,
G4double& stepLength,
G4double& lambda) {return 0.0;};
G4double MaxSecondaryEnergy(const G4DynamicParticle*);
protected:
@@ -28,15 +28,22 @@
//
// File name: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications: 03.12.2002 V.Ivanchenko fix a bug in model selection
// Modifications:
//
// Class Description:
// 03-12-02 V.Ivanchenko fix a bug in model selection
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 The set of models is defined for region (V.Ivanchenko)
// 26-03-03 Add GetDEDXDispersion (V.Ivanchenko)
// 13-04-03 Add startFromNull (V.Ivanchenko)
//
// It is the unified energy loss process it calculates the continuous
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
@@ -49,21 +56,60 @@
#ifndef G4EmModelManager_h
#define G4EmModelManager_h 1
#include "globals.hh"
#include "G4Material.hh"
#include "G4Track.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4Step;
#include "globals.hh"
#include "G4DataVector.hh"
class G4RegionModels
{
friend class G4EmModelManager;
public:
private:
G4RegionModels(G4int nMod, G4std::vector<G4int>& list, G4DataVector& lowE);
~G4RegionModels();
G4int SelectIndex(G4double e) const {
G4int idx = 0;
if (nModelsForRegion>1) {
idx = nModelsForRegion;
do {idx--;} while (idx && e <= lowKineticEnergy[idx]);
}
return theListOfModelIndexes[idx];
};
G4int ModelIndex(G4int n) const {
return theListOfModelIndexes[n];
};
G4int NumberOfModels() const {
return nModelsForRegion;
};
G4int nModelsForRegion;
G4int* theListOfModelIndexes;
G4double* lowKineticEnergy;
};
#include "G4VEmModel.hh"
#include "G4VEmFluctuationModel.hh"
#include "G4DynamicParticle.hh"
class G4Region;
class G4ParticleDefinition;
class G4VEmModel;
class G4DataVector;
class G4VParticleChange;
class G4PhysicsVector;
class G4MaterialCutsCouple;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4EmModelManager
class G4EmModelManager
{
public:
@@ -73,7 +119,7 @@ public:
void Clear();
const G4DataVector* Initialise(const G4ParticleDefinition*,
const G4DataVector* Initialise(const G4ParticleDefinition*,
const G4ParticleDefinition*,
G4double,
G4int);
@@ -82,19 +128,35 @@ public:
const G4DataVector* SubCutoff() const;
void FillDEDXVector(G4PhysicsVector*, const G4Material*);
void FillDEDXVector(G4PhysicsVector*, const G4MaterialCutsCouple*);
void FillLambdaVector(G4PhysicsVector*, const G4Material*);
void FillLambdaVector(G4PhysicsVector*, const G4MaterialCutsCouple*,
G4bool startFromNull = true);
void FillSubLambdaVector(G4PhysicsVector*, const G4Material*);
void FillSubLambdaVector(G4PhysicsVector*, const G4MaterialCutsCouple*,
G4bool startFromNull = true);
G4VEmModel* SelectModel(G4double energy);
G4VEmModel* SelectModel(G4double& energy, size_t& index);
void AddEmModel(G4VEmModel*, G4int);
G4double SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& eloss,
G4double& preStepKinEnergy,
size_t& index);
G4double GetDEDXDispersion( const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
size_t& index);
void AddEmModel(G4int, G4VEmModel*, G4VEmFluctuationModel*, const G4Region*);
private:
// hide assignment operator
// hide assignment operator
G4EmModelManager(G4EmModelManager &);
G4EmModelManager & operator=(const G4EmModelManager &right);
@@ -106,40 +168,75 @@ private:
G4DataVector theCuts;
G4DataVector theSubCuts;
G4VEmModel* emModels[5];
G4int nEmModels;
G4int nmax;
G4std::vector<G4VEmModel*> models;
G4std::vector<G4VEmFluctuationModel*> flucModels;
G4std::vector<const G4Region*> regions;
G4std::vector<G4int> orderOfModels;
G4DataVector upperEkin;
G4int order[5];
G4double upperEkin[5];
G4bool orderIsChanged;
G4int nEmModels;
G4int nRegions;
G4int nCouples;
G4std::vector<G4int> idxOfRegionModels;
G4std::vector<G4RegionModels*> setOfRegionModels;
G4double minSubRange;
const G4ParticleDefinition* particle;
const G4ParticleDefinition* secondaryParticle;
G4int verboseLevel;
G4int verboseLevel;
// cash
G4VEmModel* currentModel;
G4int currentIdx;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4VEmModel* G4EmModelManager::SelectModel(G4double energy)
inline G4VEmModel* G4EmModelManager::SelectModel(G4double& kinEnergy, size_t& index)
{
if(nEmModels == 4 && energy > upperEkin[2]) {
currentModel = emModels[3];
} else if(nEmModels >= 3 && energy > upperEkin[1]) {
currentModel = emModels[2];
} else if(nEmModels >= 2 && energy > upperEkin[0]) {
currentModel = emModels[1];
} else {
currentModel = emModels[0];
}
return currentModel;
currentIdx = (setOfRegionModels[idxOfRegionModels[index]])->SelectIndex(kinEnergy);
return models[currentIdx];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4EmModelManager::SampleFluctuations(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& eloss,
G4double& kinEnergy,
size_t& index)
{
currentIdx = (setOfRegionModels[idxOfRegionModels[index]])->SelectIndex(kinEnergy);
G4VEmFluctuationModel* fm = flucModels[currentIdx];
G4double x = eloss;
if(fm) x = fm->SampleFluctuations(material,dp,tmax,length,eloss);
return x;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4EmModelManager::GetDEDXDispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
size_t& index)
{
currentIdx = (setOfRegionModels[idxOfRegionModels[index]])
->SelectIndex(dp->GetKineticEnergy());
G4VEmFluctuationModel* fm = flucModels[currentIdx];
G4double x = 0.0;
if(fm) x = fm->Dispersion(material,dp,tmax,length);
return x;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -159,6 +256,4 @@ inline const G4DataVector* G4EmModelManager::SubCutoff() const
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -21,14 +21,14 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.hh,v 1.4 2001/07/11 10:03:40 gunter Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossMessenger.hh,v 1.5 2003/04/04 14:33:33 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
// Class Description:
// This is a messenger class to interface to exchange information
// between G4VEnergyLoss and UI.
//
//
// /process/eLoss/ directory
//
// Commands :
@@ -38,7 +38,7 @@
// subsec * Switch true/false the subcutoff generation
// minsubsec * Set the min. cut for subcutoff delta in range
// StepFunction * Set the energy loss step limitation parameters
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -59,20 +59,23 @@ class G4UIcmdWithADoubleAndUnit;
class G4EnergyLossMessenger: public G4UImessenger
{
public: // with description
G4EnergyLossMessenger();
~G4EnergyLossMessenger();
void SetNewValue(G4UIcommand*, G4String);
private:
G4UIdirectory* eLossDirectory;
G4UIdirectory* eLossDirectory;
G4UIcmdWithABool* RndmStepCmd;
G4UIcmdWithABool* EnlossFlucCmd;
G4UIcmdWithABool* SubSecCmd;
G4UIcmdWithADoubleAndUnit* MinSubSecCmd;
G4UIcommand* StepFuncCmd;
G4UIcmdWithADoubleAndUnit* MinEnCmd;
G4UIcmdWithADoubleAndUnit* MaxEnCmd;
G4UIcmdWithABool* IntegCmd;
};
#endif
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossTables.hh,v 1.12 2001/10/29 09:40:51 maire Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossTables.hh,v 1.16 2003/04/12 17:54:39 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// $Id:
//
@@ -43,7 +43,7 @@
// A utility class, containing the energy loss tables
// for each particle
//
// Energy loss processes have to register their tables with this
// Energy loss processes have to register their tables with this
// class. The responsibility of creating and deleting the tables
// remains with the energy loss classes.
// -----------------------------------------------------------------------------
@@ -51,13 +51,16 @@
// P. Urban, 06/04/1998
// L. Urban, 27/05/1988 , modifications + new functions added
// L.Urban , 13/10/98 , revision
// L.Urban, 26/10/98 , revision, Interpolate removed
// L.Urban , 08/02/99, cache mechanism
// L.Urban, 26/10/98 , revision, Interpolate removed
// L.Urban , 08/02/99, cache mechanism
// L.Urban , 12/04/99 , bug fixed
// don't use the helper class.
// It can't be hidden for Rogue Wave uses it.
// 10.11.99: moved from RWT hash dictionary to STL map, G.Barrand, M.Maire
// 26.10.01: all static functions movev from .icc to .cc file (mma)
// 15.01.03 Add interfaces required for "cut per region" (V.Ivanchenko)
// 12.03.03 Add warnings to obsolete interfaces (V.Ivanchenko)
// 12.04.03 move exception to new method (V.Ivanchenko)
//
// -----------------------------------------------------------------------------
@@ -67,10 +70,10 @@ class G4EnergyLossTablesHelper {
friend class G4EnergyLossTables;
// the only instances are within the class G4EnergyLossTables
public:
G4EnergyLossTablesHelper();
private:
G4EnergyLossTablesHelper(const G4PhysicsTable* aDEDXTable,
const G4PhysicsTable* aRangeTable,
@@ -95,6 +98,8 @@ private:
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4MaterialCutsCouple;
class G4EnergyLossTables {
public:
@@ -120,25 +125,25 @@ public:
static G4double GetRange(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetLabTime(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetDeltaLabTime(
const G4ParticleDefinition *aParticle,
G4double KineticEnergyStart,
G4double KineticEnergyEnd,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetProperTime(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetDeltaProperTime(
const G4ParticleDefinition *aParticle,
G4double KineticEnergyStart,
G4double KineticEnergyEnd,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetPreciseDEDX(
const G4ParticleDefinition *aParticle,
@@ -147,12 +152,35 @@ public:
static G4double GetPreciseRangeFromEnergy(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4Material *aMaterial);
const G4Material *aMaterial);
static G4double GetPreciseEnergyFromRange(
const G4ParticleDefinition *aParticle,
G4double range,
const G4Material *aMaterial);
const G4Material *aMaterial);
// get the DEDX or the range for a given particle/energy/materialCutsCouple
static G4double GetDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple);
static G4double GetRange(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple);
static G4double GetPreciseDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple);
static G4double GetPreciseRangeFromEnergy(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple);
static G4double GetPreciseEnergyFromRange(
const G4ParticleDefinition *aParticle,
G4double range,
const G4MaterialCutsCouple *couple);
// to be called only by energy loss processes
static void Register(
const G4ParticleDefinition* p,
@@ -170,17 +198,25 @@ public:
typedef const G4ParticleDefinition* K;
private:
static void CPRWarning();
static void ParticleHaveNoLoss(const G4ParticleDefinition* aParticle);
typedef G4std::map<K,G4EnergyLossTablesHelper,G4std::less<K> > helper_map;
static helper_map dict;
static G4EnergyLossTablesHelper GetTables(const G4ParticleDefinition* p);
static G4EnergyLossTablesHelper t ;
static G4EnergyLossTablesHelper null_loss ;
static const G4ParticleDefinition* lastParticle ;
static G4double QQPositron ;
static G4double Chargesquare ;
static G4int oldIndex ;
static G4double rmin,rmax,Thigh ;
static G4int let_counter;
static G4int let_max_num_warnings;
static G4bool first_loss;
};
@@ -26,70 +26,74 @@
// GEANT4 Class header file
//
//
// File name: G4EnergyLossMessengerSTD
// File name: G4IonFluctuations
//
// Author:
// Author: Vladimir Ivanchenko
//
// Creation date:
// Creation date: 02.04.2003
//
// Modifications: 03.01.2002 V.Ivanchenko update to new design
// Modifications:
//
// Class Description:
//
// Class Description:
// This is a messenger class to interface to exchange information
// between G4VEnergyLoss and UI.
//
// /process/eLoss/ directory
//
// Commands :
//
// rndmStep * Randomize the proposed step by eLoss (false/true)
// fluct * Switch true/false the energy loss fluctuations
// subsec * Switch true/false the subcutoff generation
// minsubsec * Set the min. cut for subcutoff delta in range
// StepFunction * Set the energy loss step limitation parameters
//
// Implementation of ion energy loss fluctuations
// -------------------------------------------------------------------
//
#ifndef G4EnergyLossMessengerSTD_h
#define G4EnergyLossMessengerSTD_h 1
#ifndef G4IonFluctuations_h
#define G4IonFluctuations_h 1
#include "globals.hh"
#include "G4UImessenger.hh"
class G4UIdirectory;
class G4UIcommand;
class G4UIcmdWithABool;
class G4UIcmdWithADoubleAndUnit;
#include "G4VEmFluctuationModel.hh"
class G4IonFluctuations : public G4VEmFluctuationModel
{
public:
G4IonFluctuations(const G4String& nam = "IonFluc");
~G4IonFluctuations();
G4double SampleFluctuations(const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&,
G4double&);
G4double Dispersion( const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&);
void Initialise(const G4ParticleDefinition*);
private:
G4double CoeffitientA(G4double&);
G4double CoeffitientB(const G4Material*, G4double&);
// hide assignment operator
G4IonFluctuations & operator=(const G4IonFluctuations &right);
G4IonFluctuations(const G4IonFluctuations&);
const G4ParticleDefinition* particle;
G4double particleMass;
G4double charge;
G4double chargeSquare;
// data members to speed up the fluctuation calculation
G4double minNumberInteractionsBohr;
G4double theBohrBeta2;
G4double minFraction;
// cash
G4double kineticEnergy;
G4double beta2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4EnergyLossMessengerSTD: public G4UImessenger
{
public: // with description
G4EnergyLossMessengerSTD();
~G4EnergyLossMessengerSTD();
void SetNewValue(G4UIcommand*, G4String);
private:
G4EnergyLossMessengerSTD & operator=(const G4EnergyLossMessengerSTD &right);
G4EnergyLossMessengerSTD(const G4EnergyLossMessengerSTD&);
G4UIdirectory* eLossDirectory;
G4UIcmdWithABool* RndmStepCmd;
G4UIcmdWithABool* EnlossFlucCmd;
G4UIcmdWithABool* SubSecCmd;
G4UIcmdWithABool* IntegCmd;
G4UIcmdWithADoubleAndUnit* MinSubSecCmd;
G4UIcmdWithADoubleAndUnit* MinEnCmd;
G4UIcmdWithADoubleAndUnit* MaxEnCmd;
G4UIcommand* StepFuncCmd;
};
#endif
@@ -0,0 +1,174 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
//
//
// File name: G4LewisModel
//
// Author: Laszlo Urban
//
// Creation date: 01.03.2001
//
// Modifications:
//
// 27-03-03 Move model part from G4MultipleScattering (V.Ivanchenko)
//
//
// Class Description:
//
// Implementation of Lewis model of multiple scattering
// H.W.Lewis Phys Rev 78 (1950) 526
// -------------------------------------------------------------------
//
#ifndef G4LewisModel_h
#define G4LewisModel_h 1
#include "G4VEmModel.hh"
class G4LewisModel : public G4VEmModel
{
public:
G4LewisModel(G4double&, G4double&, G4double&, G4double&, G4bool&,
const G4String& nam = "Lewis");
~G4LewisModel();
void Initialise(const G4ParticleDefinition*, const G4DataVector&);
G4double HighEnergyLimit(const G4ParticleDefinition*) {return highKinEnergy;};
G4double LowEnergyLimit(const G4ParticleDefinition*) {return lowKinEnergy;};
void SetHighEnergyLimit(G4double e) {highKinEnergy = e;};
void SetLowEnergyLimit(G4double e) {lowKinEnergy = e;};
G4double MinEnergyCut(const G4ParticleDefinition*,
const G4MaterialCutsCouple*) {return 0.0;};
G4bool IsInCharge(const G4ParticleDefinition*);
G4double ComputeDEDX(const G4Material*,
const G4ParticleDefinition*,
G4double kineticEnergy,
G4double cutEnergy) {return 0.0;};
G4double CrossSection(const G4Material*,
const G4ParticleDefinition*,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy);
G4DynamicParticle* SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy) {return 0;};
G4std::vector<G4DynamicParticle*>* SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double maxEnergy) {return 0;};
G4double GeomPathLength(G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* particle,
G4double& kineticEnergy,
G4double lambda,
G4double range,
G4double truePathLength);
G4double TrueStepLength(G4double geomStepLength);
G4double SampleCosineTheta(G4double trueStepLength);
G4double SampleDisplacement();
G4double MaxSecondaryEnergy(const G4DynamicParticle*) {return 0.0;};
protected:
G4double MaxSecondaryEnergy(const G4ParticleDefinition*,
G4double kinEnergy) {return 0.0;};
private:
G4double ComputeTransportCrossSection(
const G4ParticleDefinition* particle,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight);
// hide assignment operator
G4LewisModel & operator=(const G4LewisModel &right);
G4LewisModel(const G4LewisModel&);
const G4ParticleDefinition* particle;
G4double mass;
G4double chargeSquare;
G4double massRate;
G4double highKinEnergy;
G4double lowKinEnergy;
G4double taubig;
G4double tausmall;
G4double taulim;
G4double currentTau;
G4double dtrl;
G4double NuclCorrPar;
G4double FactPar;
G4double facxsi;
G4double sigmafactor;
G4double alfa1;
G4double alfa2;
G4double alfa3;
G4double b;
G4double xsi;
G4double c0;
G4double lambda0;
G4double lambda1;
G4double lambdam;
G4double alam;
G4double zm;
G4double cthm;
G4double tPathLength;
G4bool samplez;
G4double stepmin ;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -30,19 +30,25 @@
// File name: G4LossTableManager
//
// Author: Vladimir Ivanchenko on base of G4LossTables class
// and Maria Grazia Pia ideas
//
// and Maria Grazia Pia ideas
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 17-02-03 Fix problem of store/restore tables for ions (V.Ivanchenko)
// 10-03-03 Add Ion registration (V.Ivanchenko)
// 25-03-03 Add deregistration (V.Ivanchenko)
// 26-03-03 Add GetDEDXDispersion (V.Ivanchenko)
// 02-04-03 Change messenger (V.Ivanchenko)
//
// Class Description:
// Class Description:
//
// A utility static class, responsable for the energy loss tables
// for each particle
//
// Energy loss processes have to register their tables with this
// Energy loss processes have to register their tables with this
// class. The responsibility of creating and deleting the tables
// remains with the energy loss classes.
@@ -60,11 +66,12 @@
#include "G4VEnergyLossSTD.hh"
class G4PhysicsTable;
class G4Material;
class G4EnergyLossMessengerSTD;
class G4MaterialCutsCouple;
class G4EnergyLossMessenger;
class G4ParticleDefinition;
class G4VMultipleScattering;
class G4LossTableManager
class G4LossTableManager
{
public:
@@ -79,25 +86,37 @@ public:
G4double GetDEDX(
const G4ParticleDefinition *aParticle,
G4double kineticEnergy,
const G4Material *aMaterial);
const G4MaterialCutsCouple *couple);
G4double GetRange(
const G4ParticleDefinition *aParticle,
G4double kineticEnergy,
const G4Material *aMaterial);
const G4MaterialCutsCouple *couple);
G4double GetEnergy(
const G4ParticleDefinition *aParticle,
G4double range,
const G4Material *aMaterial);
const G4MaterialCutsCouple *couple);
G4double GetDEDXDispersion(
const G4MaterialCutsCouple *couple,
const G4DynamicParticle* dp,
G4double& length);
// to be called only by energy loss processes
void Register(G4VEnergyLossSTD* p);
void BuildDEDXTable(const G4ParticleDefinition* aParticle);
void DeRegister(G4VEnergyLossSTD* p);
void RetrieveDEDXTable(const G4ParticleDefinition* aParticle,
G4VEnergyLossSTD*);
void Register(G4VMultipleScattering* p);
void DeRegister(G4VMultipleScattering* p);
void RegisterIon(const G4ParticleDefinition* aParticle, G4VEnergyLossSTD* p);
void BuildPhysicsTable(const G4ParticleDefinition* aParticle);
void RetrievePhysicsTables(const G4ParticleDefinition* aParticle, G4VEnergyLossSTD* em);
void SetLossFluctuations(G4bool val);
@@ -115,22 +134,17 @@ public:
void SetStepLimits(G4double v1, G4double v2);
G4bool StorePhysicsTable(G4VEnergyLossSTD* el,
const G4String& dedx_file,
const G4String& range_file,
const G4String& inv_range_file,
G4bool ascii);
G4EnergyLossMessenger* GetMessenger();
private:
G4LossTableManager();
void Initialise();
void Initialise(const G4ParticleDefinition*);
G4VEnergyLossSTD* BuildTables(const G4ParticleDefinition* aParticle);
// G4LossTableManager(const G4LossTableManager&);
// const G4LossTableManager& operator=(const G4LossTableManager& right);
void ParticleHaveNoLoss(const G4ParticleDefinition* aParticle);
private:
@@ -146,6 +160,7 @@ private:
G4std::vector<G4PhysicsTable*> dedx_vector;
G4std::vector<G4PhysicsTable*> range_vector;
G4std::vector<G4PhysicsTable*> inv_range_vector;
G4std::vector<G4VMultipleScattering*> msc_vector;
// cash
G4VEnergyLossSTD* currentLoss;
@@ -153,14 +168,15 @@ private:
PD theElectron;
G4int n_loss;
G4bool all_tables_are_built;
G4bool all_particles_are_mapped;
G4bool first_entry;
G4bool electron_table_are_built;
G4bool lossFluctuationFlag;
G4bool subCutoffFlag;
G4bool rndmStepFlag;
G4bool integral;
G4bool all_tables_are_stored;
G4double minSubRange;
G4double maxRangeVariation;
@@ -170,7 +186,8 @@ private:
G4VEnergyLossSTD* eIonisation;
G4LossTableBuilder* tableBuilder;
G4EnergyLossMessengerSTD* theMessenger;
G4EnergyLossMessenger* theMessenger;
const G4ParticleDefinition* firstParticle;
G4int verbose;
};
@@ -181,15 +198,18 @@ private:
inline G4double G4LossTableManager::GetDEDX(
const G4ParticleDefinition *aParticle,
G4double kineticEnergy,
const G4Material *aMaterial)
const G4MaterialCutsCouple *couple)
{
if(aParticle != currentParticle) {
G4std::map<PD, G4VEnergyLossSTD*,G4std::less<PD> >::const_iterator pos;
if((pos = loss_map.find(aParticle)) == loss_map.end()) return 0.0;
currentParticle = aParticle;
currentLoss = (*pos).second;
if ((pos = loss_map.find(aParticle)) != loss_map.end()) {
currentParticle = aParticle;
currentLoss = (*pos).second;
} else {
ParticleHaveNoLoss(aParticle);
}
}
return currentLoss->GetDEDX(kineticEnergy, aMaterial);
return currentLoss->GetDEDX(kineticEnergy, couple);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -197,15 +217,18 @@ inline G4double G4LossTableManager::GetDEDX(
inline G4double G4LossTableManager::GetRange(
const G4ParticleDefinition *aParticle,
G4double kineticEnergy,
const G4Material *aMaterial)
const G4MaterialCutsCouple *couple)
{
if(aParticle != currentParticle) {
G4std::map<PD, G4VEnergyLossSTD*, G4std::less<PD> >::const_iterator pos;
if((pos = loss_map.find(aParticle)) == loss_map.end()) return 0.0;
currentParticle = aParticle;
currentLoss = (*pos).second;
if ((pos = loss_map.find(aParticle)) != loss_map.end()) {
currentParticle = aParticle;
currentLoss = (*pos).second;
} else {
ParticleHaveNoLoss(aParticle);
}
}
return currentLoss->GetRange(kineticEnergy, aMaterial);
return currentLoss->GetRange(kineticEnergy, couple);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -213,15 +236,38 @@ inline G4double G4LossTableManager::GetRange(
inline G4double G4LossTableManager::GetEnergy(
const G4ParticleDefinition *aParticle,
G4double range,
const G4Material *aMaterial)
const G4MaterialCutsCouple *couple)
{
if(aParticle != currentParticle) {
G4std::map<PD,G4VEnergyLossSTD*,G4std::less<PD> >::const_iterator pos;
if((pos = loss_map.find(aParticle)) == loss_map.end()) return 0.0;
currentParticle = aParticle;
currentLoss = (*pos).second;
if ((pos = loss_map.find(aParticle)) != loss_map.end()) {
currentParticle = aParticle;
currentLoss = (*pos).second;
} else {
ParticleHaveNoLoss(aParticle);
}
}
return currentLoss->GetKineticEnergy(range, aMaterial);
return currentLoss->GetKineticEnergy(range, couple);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4LossTableManager::GetDEDXDispersion(
const G4MaterialCutsCouple *couple,
const G4DynamicParticle* dp,
G4double& length)
{
const G4ParticleDefinition* aParticle = dp->GetDefinition();
if(aParticle != currentParticle) {
G4std::map<PD,G4VEnergyLossSTD*,G4std::less<PD> >::const_iterator pos;
if ((pos = loss_map.find(aParticle)) != loss_map.end()) {
currentParticle = aParticle;
currentLoss = (*pos).second;
} else {
ParticleHaveNoLoss(aParticle);
}
}
return currentLoss->GetDEDXDispersion(couple, dp, length);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MultipleScattering.hh,v 1.11 2002/10/30 11:30:47 urban Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScattering.hh,v 1.16 2003/04/18 12:44:04 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//------------- G4MultipleScattering physics process --------------------------
// by Laszlo Urban, March 2001
@@ -40,6 +40,8 @@
// 24-04-02 some minor changes in boundary algorithm, L.Urban
// 24-05-02 changes in data members, L.Urban
// 30-10-02 changes in data members, L.Urban
// 05-02-03 changes in data members, L.Urban
// 18-04-03 Change signature of GetTransportMeanFreePath (V.Ivanchenko)
//------------------------------------------------------------------------------
// class description
@@ -125,12 +127,12 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
// This function overloads a virtual function of the base class.
// It is invoked by the ProcessManager of the Particle.
G4double GetTransportMeanFreePath(
G4double KineticEnergy,G4Material* material);
G4double KineticEnergy,const G4MaterialCutsCouple* couple);
// Just a utility method to get the values of the transport
// mean free path . (It is not used inside the class.)
G4VParticleChange* AlongStepDoIt(const G4Track& aTrack,const G4Step& aStep);
// The geometrical step length --> true path length transformation
// is performed here (the inverse of the transformation done
@@ -143,8 +145,8 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
// This function overloads a virtual function of the base class.
// It is invoked by the ProcessManager of the Particle.
void Setpcz(G4double value) {pcz = value;};
// geom. step length distribution
void Setsamplez(G4bool value) {samplez = value;};
// geom. step length distribution should be sampled or not
void Setdtrl(G4double value) {dtrl = value;};
// to reduce the energy/step dependence
@@ -160,6 +162,7 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
// Steplimit after boundary crossing = facrange*range
// estimated nb of steps at boundary nsmallstep = 1/facrange
void SetLateralDisplacementFlag(G4bool flag) {fLatDisplFlag = flag;};
// lateral displacement to be/not to be computed
@@ -186,8 +189,6 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
G4PhysicsTable* theTransportMeanFreePathTable;
G4double fTransportMeanFreePath,kappa;
G4double taubig,tausmall,taulim;
G4double LowestKineticEnergy;
@@ -206,11 +207,12 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
G4double laststep ;
G4GPILSelection valueGPILSelectionMSC;
G4double pcz,zmean; // z(geom.step length)
// distribution
G4double zmean; // z(geom.step length)
G4bool samplez ; // distribution
G4double range,T1,lambda1,cth1,z1,t1,dtrl; // used to reduce the energy
// (or step length) dependence
G4double range,T0,T1,lambda0,lambda1, // used to reduce the energy
Tlow,alam,blam,dtrl,lambdam, // (or step length) dependence
clam,zm,cthm;
// with/without lateral displacement
G4bool fLatDisplFlag;
@@ -221,10 +223,9 @@ class G4MultipleScattering : public G4VContinuousDiscreteProcess
G4ParticleChangeForMSC fParticleChange;
G4double alfa1,alfa2,alfa3,xsi,c0,facxsi ; // angle distr. parameters
G4double alfa1,alfa2,alfa3,b,xsi,c0,facxsi ; // angle distr. parameters
// facxsi : some tuning
// possibility in the tail
};
#include "G4MultipleScattering.icc"
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MultipleScattering.icc,v 1.7 2002/05/24 06:11:24 urban Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScattering.icc,v 1.9 2003/04/18 12:44:05 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//------------ G4MultipleScattering physics process ---------------------------
// by Laszlo Urban, March 2001
@@ -34,17 +34,19 @@
// 27-08-01 bugfix in AlongStepDoIt, L.Urban
// 28-08-01 GetContinuousStepLimit and AlongStepDoIt moved to .cc file (mma)
// 11-09-01 G4MultipleScatteringx put as default: G4MultipleScattering (mma)
// 15-01-03 Migrade to cut per region (V.Ivanchenko)
// 18-04-03 Change signature of GetTransportMeanFreePath (V.Ivanchenko)
//
//------------------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline
inline
G4bool G4MultipleScattering::IsApplicable(const G4ParticleDefinition& particle)
{
return(particle.GetPDGCharge() != 0.);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4MultipleScattering::AlongStepGetPhysicalInteractionLength(
@@ -79,14 +81,15 @@ inline G4double G4MultipleScattering::GetMeanFreePath(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline
inline
G4double G4MultipleScattering::GetTransportMeanFreePath(G4double KineticEnergy,
G4Material* material)
const G4MaterialCutsCouple* couple)
{
G4bool isOut;
return (*theTransportMeanFreePathTable)
(material->GetIndex())->GetValue(KineticEnergy,isOut);
(couple->GetIndex())->GetValue(KineticEnergy,isOut);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -21,24 +21,26 @@
// ********************************************************************
//
//
//
//------------- G4MultipleScattering physics process --------------------------
// by Laszlo Urban, March 2001
//
// 07-08-01 new methods Store/Retrieve PhysicsTable
//------------- G4MultipleScattering physics process --------------------------
// by Laszlo Urban, March 2001
//
// 07-08-01 new methods Store/Retrieve PhysicsTable
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 11-09-01 G4MultipleScatteringx put as default: G4MultipleScattering
// Store,Retrieve methods reactived (mma)
// 13-09-01 Unused TrueToGeomTransformation method deleted,
// class description (L.Urban)
// 19-09-01 come back to previous process name msc
// 19-09-01 come back to previous process name msc
// 17-04-02 NEW angle distribution + boundary algorithm modified, L.Urban
// 22-04-02 boundary algorithm modified -> important improvement in timing !!!!
// (L.Urban)
// 24-05-02 changes in data members, L.Urban
// 30-10-02 changes in data members, L.Urban
//
// 30-10-02 changes in data members, L.Urban
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 05-02-03 changes in data members, L.Urban
//
//------------------------------------------------------------------------------
// class description
@@ -96,8 +98,8 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4bool RetrievePhysicsTable(G4ParticleDefinition* ,
const G4String& directory, G4bool);
// retrieve TransportMeanFreePath tables from an external file
// specified by 'directory'
// specified by 'directory'
G4double AlongStepGetPhysicalInteractionLength(const G4Track&,
G4double previousStepSize,
@@ -105,16 +107,16 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4double& currentSafety,
G4GPILSelection* selection);
// The function overloads the corresponding function of the base
// class.It limits the step near to boundaries only
// and invokes the method GetContinuousStepLimit at every step.
// class.It limits the step near to boundaries only
// and invokes the method GetContinuousStepLimit at every step.
G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety);
G4double& currentSafety);
// It performs the true step length --> geometrical step length
// transformation. It is invoked by the
// AlongStepGetPhysicalInteractionLength method.
// AlongStepGetPhysicalInteractionLength method.
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
@@ -124,26 +126,26 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
// This function overloads a virtual function of the base class.
// It is invoked by the ProcessManager of the Particle.
G4double GetTransportMeanFreePath(
G4double KineticEnergy,G4Material* material);
G4double KineticEnergy,const G4MaterialCutsCouple* couple);
// Just a utility method to get the values of the transport
// mean free path . (It is not used inside the class.)
G4VParticleChange* AlongStepDoIt(const G4Track& aTrack,const G4Step& aStep);
// The geometrical step length --> true path length transformation
// is performed here (the inverse of the transformation done
// by GetContinuousStepLimit).
// by GetContinuousStepLimit).
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,const G4Step& aStep);
// It computes the final state of the particle: samples the
// It computes the final state of the particle: samples the
// ScatteringSTD angle and computes the lateral displacement.
// The final state is returned as a ParticleChange object.
// This function overloads a virtual function of the base class.
// It is invoked by the ProcessManager of the Particle.
void Setpcz(G4double value) {pcz = value;};
// geom. step length distribution
void Setsamplez(G4bool value) {samplez = value;};
// geom. step length distribution should be sampled or not
void Setdtrl(G4double value) {dtrl = value;};
// to reduce the energy/step dependence
@@ -154,17 +156,17 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
void SetFacrange(G4double val) {facrange=val;
nsmallstep = G4int(log((cf+facrange-1.)/
facrange)/log(cf))+1 ;
G4cout << " fr=" << facrange
G4cout << " fr=" << facrange
<< " nsmall=" << nsmallstep << G4endl ;};
// Steplimit after boundary crossing = facrange*range
// estimated nb of steps at boundary nsmallstep = 1/facrange
void SetLateralDisplacementFlag(G4bool flag) {fLatDisplFlag = flag;};
// lateral displacement to be/not to be computed
void SetNuclCorrPar(G4double val) {NuclCorrPar = val;};
void SetFactPar(G4double val) {FactPar = val;};
// corrs to transport cross section for high energy
// corrs to transport cross section for high energy
protected: // with description
@@ -174,7 +176,7 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4double AtomicNumber,
G4double AtomicWeight);
// It computes the transport cross section.
// The transport mean free path is 1/(transport cross section).
// The transport mean free path is 1/(transport cross section).
private:
@@ -186,8 +188,6 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4PhysicsTable* theTransportMeanFreePathTable;
G4double fTransportMeanFreePath,kappa;
G4double taubig,tausmall,taulim;
G4double LowestKineticEnergy;
@@ -195,7 +195,7 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4int TotBin;
G4int materialIndex;
G4double tLast;
G4double zLast;
@@ -206,12 +206,12 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4double laststep ;
G4GPILSelection valueGPILSelectionMSC;
G4double pcz,zmean; // z(geom.step length)
// distribution
G4double range,T1,lambda1,cth1,z1,t1,dtrl; // used to reduce the energy
// (or step length) dependence
G4double zmean; // z(geom.step length)
G4bool samplez ; // distribution
G4double range,T0,T1,lambda0,lambda1, // used to reduce the energy
Tlow,alam,blam,dtrl,lambdam, // (or step length) dependence
clam,zm,cthm;
// with/without lateral displacement
G4bool fLatDisplFlag;
@@ -222,7 +222,7 @@ class G4MultipleScatteringSTD : public G4VContinuousDiscreteProcess
G4ParticleChangeForMSC fParticleChange;
G4double alfa1,alfa2,alfa3,xsi,c0,facxsi ; // angle distr. parameters
G4double alfa1,alfa2,alfa3,b,xsi,c0,facxsi ; // angle distr. parameters
// facxsi : some tuning
// possibility in the tail
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4MultipleScatteringSTD.icc,v 1.1 2002/10/11 16:41:12 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScatteringSTD.icc,v 1.4 2003/04/24 16:49:46 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//------------ G4MultipleScattering physics process ---------------------------
// by Laszlo Urban, March 2001
@@ -40,12 +40,12 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline
inline
G4bool G4MultipleScatteringSTD::IsApplicable(const G4ParticleDefinition& particle)
{
return(particle.GetPDGCharge() != 0.);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4MultipleScatteringSTD::AlongStepGetPhysicalInteractionLength(
@@ -80,14 +80,14 @@ inline G4double G4MultipleScatteringSTD::GetMeanFreePath(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline
inline
G4double G4MultipleScatteringSTD::GetTransportMeanFreePath(G4double KineticEnergy,
G4Material* material)
const G4MaterialCutsCouple* couple)
{
G4bool isOut;
return (*theTransportMeanFreePathTable)
(material->GetIndex())->GetValue(KineticEnergy,isOut);
(couple->GetIndex())->GetValue(KineticEnergy,isOut);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -29,12 +29,17 @@
// File name: G4SCProcessorStand
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 29-12-02 Change interface (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// Class for simualtion of subCutoff
@@ -50,24 +55,26 @@
#include "G4DataVector.hh"
class G4Navigator;
class G4Material;
class G4MaterialCutsCouple;
class G4SCProcessorStand : public G4VSubCutoffProcessor
{
public:
G4SCProcessorStand();
G4SCProcessorStand(const G4String& nam = "ProcSTD");
~G4SCProcessorStand();
virtual G4std::vector<G4Track*>* SampleSecondary(const G4Step& step,
const G4DynamicParticle*,
G4double meanLoss);
virtual G4std::vector<G4Track*>* SampleSecondaries(const G4Step&,
G4double& tmax,
G4double& meanLoss,
G4VEmModel*) = 0;
virtual void Initialise(const G4ParticleDefinition*,
const G4ParticleDefinition*,
G4EmModelManager* );
const G4ParticleDefinition*,
const G4DataVector*,
const G4DataVector*) = 0;
virtual void SetLambdaSubTable(G4PhysicsTable*);
@@ -77,7 +84,7 @@ protected:
private:
// hide assignment operator
// hide assignment operator
G4SCProcessorStand & operator=(const G4SCProcessorStand &right);
G4SCProcessorStand(const G4SCProcessorStand&);
@@ -85,18 +92,11 @@ private:
const G4ParticleDefinition* particle;
const G4ParticleDefinition* secondaryParticle;
const G4ParticleDefinition* thePositron;
G4EmModelManager* modelManager;
G4Navigator* navigator;
const G4DataVector* theCuts;
const G4DataVector* theSubCuts;
G4DataVector rangeCuts;
// cash
const G4Material* material;
G4int materialIndex;
G4double cut;
G4double subcut;
G4double rcut;
G4double initialMass;
};
@@ -111,7 +111,7 @@ inline void G4SCProcessorStand::SetLambdaSubTable(G4PhysicsTable* table)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4PhysicsTable* G4SCProcessorStand::LambdaSubTable()
inline G4PhysicsTable* G4SCProcessorStand::LambdaSubTable()
{
return theLambdaSubTable;
}
@@ -32,7 +32,12 @@
//
// Creation date: 03.01.2002
//
// Modifications: 09.12.2002 VI remove warnings
// Modifications:
//
// 09-12-02 remove warnings (V.Ivanchenko)
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
@@ -52,34 +57,41 @@ class G4UniversalFluctuation : public G4VEmFluctuationModel
public:
G4UniversalFluctuation();
G4UniversalFluctuation(const G4String& nam = "UniFluc");
~G4UniversalFluctuation();
virtual void SampleFluctuations(const G4Material*, const G4DynamicParticle*,
G4double&, G4double&, G4double);
G4double SampleFluctuations(const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&,
G4double&);
virtual void Initialise(const G4ParticleDefinition*);
G4double Dispersion( const G4Material*,
const G4DynamicParticle*,
G4double&,
G4double&);
void Initialise(const G4ParticleDefinition*);
protected:
private:
// hide assignment operator
// hide assignment operator
G4UniversalFluctuation & operator=(const G4UniversalFluctuation &right);
G4UniversalFluctuation(const G4UniversalFluctuation&);
const G4ParticleDefinition* particle;
const G4Material* lastMaterial;
G4double particleMass;
G4double chargeSquare;
const G4Material* lastMaterial;
G4int materialIndex;
// data members to speed up the fluctuation calculation
G4double ipotFluct;
G4double electronDensity;
G4double zeff;
// G4double zeff;
G4double f1Fluct;
G4double f2Fluct;
@@ -34,6 +34,11 @@
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
//
// Class Description:
//
// Abstract class for interface to simualtion of energy loss fluctuations
@@ -56,23 +61,34 @@ class G4VEmFluctuationModel
public:
G4VEmFluctuationModel() {};
G4VEmFluctuationModel(const G4String& nam): name(nam) {};
virtual ~G4VEmFluctuationModel() {};
virtual void SampleFluctuations(const G4Material*, const G4DynamicParticle*,
G4double& tmax, G4double& length, G4double meanLoss) = 0;
virtual G4double SampleFluctuations(const G4Material*,
const G4DynamicParticle*,
G4double& tmax,
G4double& length,
G4double& meanLoss) = 0;
virtual G4double Dispersion(const G4Material*,
const G4DynamicParticle*,
G4double& tmax,
G4double& length) = 0;
virtual void Initialise(const G4ParticleDefinition*) = 0;
G4String GetName() const {return name;};
protected:
private:
// hide assignment operator
// hide assignment operator
G4VEmFluctuationModel & operator=(const G4VEmFluctuationModel &right);
G4VEmFluctuationModel(const G4VEmFluctuationModel&);
const G4String name;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -29,13 +29,19 @@
// File name: G4VEmModel
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// 23-12-02 V.Ivanchenko change interface before move to cut per region
// 24-01-03 Cut per region (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// 25-02-03 Add sample theta and displacement (V.Ivanchenko)
//
//
// Class Description:
// Class Description:
//
// Abstract interface to energy loss models
@@ -50,32 +56,34 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4ThreeVector.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4DataVector.hh"
class G4VEmModel
class G4PhysicsTable;
class G4VEmModel
{
public:
G4VEmModel() {};
G4VEmModel(const G4String& nam): name(nam) {};
virtual ~G4VEmModel() {};
virtual G4double HighEnergyLimit(const G4ParticleDefinition*,
const G4Material*) = 0;
virtual G4double LowEnergyLimit(const G4ParticleDefinition*,
const G4Material*) = 0;
virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&) = 0;
virtual void SetHighEnergyLimit(const G4Material*, G4double) = 0;
virtual void SetLowEnergyLimit(const G4Material*, G4double) = 0;
virtual G4double HighEnergyLimit(const G4ParticleDefinition*) = 0;
virtual G4double LowEnergyLimit(const G4ParticleDefinition*) = 0;
virtual void SetHighEnergyLimit(G4double) = 0;
virtual void SetLowEnergyLimit(G4double) = 0;
virtual G4double MinEnergyCut(const G4ParticleDefinition*,
const G4Material*) = 0;
virtual G4bool IsInCharge(const G4ParticleDefinition*,
const G4Material*) = 0;
const G4MaterialCutsCouple*) = 0;
virtual G4bool IsInCharge(const G4ParticleDefinition*) = 0;
virtual G4double ComputeDEDX(const G4Material*,
const G4ParticleDefinition*,
@@ -88,26 +96,49 @@ public:
G4double cutEnergy,
G4double maxEnergy) = 0;
virtual G4std::vector<G4DynamicParticle*>* SampleSecondary(
const G4Material*,
virtual G4DynamicParticle* SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double tmax) = 0;
virtual G4std::vector<G4DynamicParticle*>* SampleSecondaries(
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double tmin,
G4double tmax) = 0;
virtual G4double GeomPathLength(G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* particle,
G4double& kineticEnergy,
G4double lambda,
G4double range,
G4double truePathLength) {return truePathLength;};
virtual G4double TrueStepLength(G4double geomStepLength) {return geomStepLength;};
virtual G4double SampleCosineTheta(G4double trueStepLength) {return 1.0;};
virtual G4double SampleDisplacement() {return 0.0;};
virtual G4double MaxSecondaryEnergy(
const G4DynamicParticle* dynParticle) = 0;
const G4DynamicParticle* dynParticle) = 0;
G4String GetName() const {return name;};
protected:
virtual G4double MaxSecondaryEnergy(const G4ParticleDefinition*,
G4double kineticEnergy) = 0;
G4double kineticEnergy) = 0;
private:
// hide assignment operator
// G4VEmModel & operator=(const G4VEmModel &right);
// G4VEmModel(const G4VEmModel&);
// hide assignment operator
G4VEmModel & operator=(const G4VEmModel &right);
G4VEmModel(const G4VEmModel&);
const G4String name;
};
#endif
@@ -21,19 +21,20 @@
// ********************************************************************
//
//
// $Id: G4VEnergyLoss.hh,v 1.14 2002/09/02 15:46:55 maire Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4VEnergyLoss.hh,v 1.17 2003/03/25 13:36:57 maire Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
//
// ------------------------------------------------------------
// 26.10.01 static inline functions moved to .cc file (mma)
// 08.11.01 some static methods,data members are not static L.Urban
// 15.01.03 Migrade to cut per region (V.Ivanchenko)
// ------------------------------------------------------------
//
// Class Description
//
// Class Description
//
// General service class for the energy loss classes
//
//
// It contains code needed to compute the range tables,
// time tables, the inverse range tables and some auxiliary
// tables.
@@ -44,7 +45,7 @@
//
// -----------------------------------------------------------
// created on 28 January 2000 by L. Urban
// created on 28 January 2000 by L. Urban
// -----------------------------------------------------------
#ifndef G4VEnergyLoss_h
@@ -58,12 +59,13 @@
#include "G4VContinuousDiscreteProcess.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsLinearVector.hh"
#include "G4MaterialCutsCouple.hh"
class G4EnergyLossMessenger;
class G4VEnergyLoss : public G4VContinuousDiscreteProcess
class G4VEnergyLoss : public G4VContinuousDiscreteProcess
{
public:
public:
G4VEnergyLoss(const G4String& ,
G4ProcessType aType = fNotDefined );
@@ -93,7 +95,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
// code for the energy loss fluctuation
G4double GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
const G4MaterialCutsCouple* couple,
G4double ChargeSquare,
G4double MeanLoss,
G4double step);
@@ -115,7 +117,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
G4PhysicsTable* ProperTimeTable,
G4double Tmin,G4double Tmax,G4int nbin);
// Build tables of coefficients needed for inverting the range table
// Build tables of coefficients needed for inverting the range table
G4PhysicsTable*
BuildRangeCoeffATable(G4PhysicsTable* theRangeTable,
G4PhysicsTable* theCoeffATable,
@@ -140,7 +142,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
private:
// hide default constructor and assignment operator as private
// hide default constructor and assignment operator as private
G4VEnergyLoss();
G4VEnergyLoss & operator=(const G4VEnergyLoss &right);
@@ -179,7 +181,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
private:
// data members to speed up the fluctuation calculation
G4Material* lastMaterial;
const G4Material* lastMaterial;
G4int imat;
G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
G4double e1LogFluct,e2LogFluct,ipotLogFluct;
@@ -189,7 +191,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
// for some integration routines
G4double taulow,tauhigh,ltaulow,ltauhigh;
// static part of the class
// static part of the class
public: // With description
@@ -219,8 +221,9 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
protected: // With description
static G4bool EqualCutVectors( G4double* vec1, G4double* vec2 );
static G4bool EqualCutVectors( G4double* vec1, G4double* vec2 );
static G4double* CopyCutVectors( G4double* dest, G4double* source );
G4bool CutsWhereModified();
// data members
protected:
@@ -228,6 +231,7 @@ class G4VEnergyLoss : public G4VContinuousDiscreteProcess
static G4double dRoverRange; // dRoverRange is the maximum allowed
// deltarange/range in one Step
static G4double finalRange; // final step before stopping
static G4double finalRangeRequested; //from UI command
static G4double c1lim,c2lim,c3lim ; // coeffs for computing steplimit
static G4bool rndmStepFlag; // control the randomization of the step
@@ -26,17 +26,27 @@
// GEANT4 Class header file
//
//
// File name: G4BetheBlochModel
// File name: G4VEnergyLossSTD
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 24-01-03 Make models region aware (V.Ivanchenko)
// 05-02-03 Fix compilation warnings (V.Ivanchenko)
// 13-02-03 SubCutoffProcessors defined for regions (V.Ivanchenko)
// 17-02-03 Fix problem of store/restore tables (V.Ivanchenko)
// 26-02-03 Region dependent step limit (V.Ivanchenko)
// 26-03-03 Add GetDEDXDispersion (V.Ivanchenko)
// 09-04-03 Fix problem of negative range limit for non integral (V.Ivanchenko)
//
// It is the unified energy loss process it calculates the continuous
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
@@ -51,41 +61,56 @@
#include "G4VContinuousDiscreteProcess.hh"
#include "globals.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Track.hh"
#include "G4EmModelManager.hh"
class G4Step;
class G4ParticleDefinition;
class G4VEmModel;
class G4VEffectiveChargeModel;
class G4VEmFluctuationModel;
class G4DataVector;
class G4VParticleChange;
class G4PhysicsTable;
class G4PhysicsVector;
class G4VSubCutoffProcessor;
class G4Region;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4VEnergyLossSTD : public G4VContinuousDiscreteProcess
class G4VEnergyLossSTD : public G4VContinuousDiscreteProcess
{
public:
G4VEnergyLossSTD(const G4String& name = "EnergyLoss",
G4VEnergyLossSTD(const G4String& name = "EnergyLoss",
G4ProcessType type = fElectromagnetic);
~G4VEnergyLossSTD();
void Initialise();
virtual G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&);
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&);
virtual G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&);
G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&);
virtual G4bool IsApplicable(const G4ParticleDefinition& p);
virtual G4std::vector<G4Track*>* SecondariesAlongStep(
const G4Step&,
G4double& tmax,
G4double& eloss,
G4double& kinEnergy) = 0;
virtual void SecondariesPostStep(
G4VEmModel*,
const G4MaterialCutsCouple*,
const G4DynamicParticle*,
G4double& tcut,
G4double& kinEnergy) = 0;
virtual G4bool IsApplicable(const G4ParticleDefinition& p) = 0;
// True for all charged particles
virtual void BuildPhysicsTable(const G4ParticleDefinition&);
virtual
void BuildPhysicsTable(const G4ParticleDefinition&);
// Build physics table during initialisation
virtual void PrintInfoDefinition() const;
@@ -93,13 +118,17 @@ public:
G4PhysicsTable* BuildDEDXTable();
void SetParticles(const G4ParticleDefinition*,
G4PhysicsTable* BuildLambdaTable();
G4PhysicsTable* BuildLambdaSubTable();
void SetParticles(const G4ParticleDefinition*,
const G4ParticleDefinition*,
const G4ParticleDefinition*);
void SetParticle(const G4ParticleDefinition* p);
void SetBaseParticle(const G4ParticleDefinition* p);
void SetSecondaryParticle(const G4ParticleDefinition* p);
void SetParticle(const G4ParticleDefinition* p);
void SetBaseParticle(const G4ParticleDefinition* p);
void SetSecondaryParticle(const G4ParticleDefinition* p);
const G4ParticleDefinition* Particle() const;
const G4ParticleDefinition* BaseParticle() const;
@@ -123,25 +152,27 @@ public:
// Print out of the class parameters
G4bool StorePhysicsTable(G4ParticleDefinition*,
const G4String& directory,
const G4String& directory,
G4bool ascii = false);
// Store PhysicsTable in a file.
// Store PhysicsTable in a file.
// Return false in case of failure at I/O
G4bool RetrievePhysicsTable(G4ParticleDefinition*,
const G4String& directory,
const G4String& directory,
G4bool ascii);
// Retrieve Physics from a file.
// Retrieve Physics from a file.
// (return true if the Physics Table can be build by using file)
// (return false if the process has no functionality or in case of failure)
// File name should is constructed as processName+particleName and the
// should be placed under the directory specifed by the argument.
// File name should is constructed as processName+particleName and the
// should be placed under the directory specifed by the argument.
void AddEmModel(G4VEmModel*, G4int);
void AddEmModel(G4int, G4VEmModel*, G4VEmFluctuationModel* fluc = 0,
const G4Region* region = 0);
void AddEmFluctuationModel(G4VEmFluctuationModel*);
void AddSubCutoffProcessor(G4VSubCutoffProcessor*, const G4Region* region = 0);
void SetSubCutoffProcessor(G4VSubCutoffProcessor*);
virtual
void SetSubCutoff(G4bool) {};
void SetDEDXTable(G4PhysicsTable* p);
G4PhysicsTable* DEDXTable() const {return theDEDXTable;};
@@ -154,27 +185,34 @@ public:
void SetSecondaryRangeTable(G4PhysicsTable* p);
const G4PhysicsTable* LambdaTable() {return theLambdaTable;};
void SetLambdaTable(G4PhysicsTable* p);
G4PhysicsTable* LambdaTable() {return theLambdaTable;};
G4double GetDEDX(G4double kineticEnergy, const G4Material* material);
void SetSubLambdaTable(G4PhysicsTable* p);
G4PhysicsTable* SubLambdaTable() {return theSubLambdaTable;};
G4double GetRange(G4double kineticEnergy, const G4Material* material);
G4double GetDEDX(G4double& kineticEnergy, const G4MaterialCutsCouple* couple);
G4double GetKineticEnergy(G4double range, const G4Material* material);
G4double GetRange(G4double& kineticEnergy, const G4MaterialCutsCouple* couple);
G4double GetLambda(G4double kineticEnergy, const G4Material* material);
G4double GetKineticEnergy(G4double& range, const G4MaterialCutsCouple* couple);
G4double GetLambda(G4double kineticEnergy, const G4MaterialCutsCouple* couple);
// It returns the MeanFreePath of the process for a (energy, material)
G4double MicroscopicCrossSection(G4double kineticEnergy, const G4Material* material);
G4double GetDEDXDispersion(const G4MaterialCutsCouple *couple,
const G4DynamicParticle* dp,
G4double& length);
G4double MicroscopicCrossSection(G4double kineticEnergy,
const G4MaterialCutsCouple* couple);
// It returns the MeanFreePath of the process for a (energy, material)
void SetLinearLossLimit(G4double val) {linLossLimit = val;};
void SetLossFluctuations(G4bool val) {lossFluctuationFlag = val;};
void SetSubCutoff(G4bool val) {if(subCutoffIsDesired) subCutoffFlag = val;};
void SetIntegral(G4bool val) {integral = val;};
void SetIntegral(G4bool val) {integral = val;};
void SetRandomStep(G4bool val) {rndmStepFlag = val;};
@@ -182,7 +220,9 @@ public:
void SetStepLimits(G4double v1, G4double v2);
G4bool TablesAreBuilt() {return tablesAreBuilt;};
G4bool TablesAreBuilt() const {return tablesAreBuilt;};
G4int NumberOfSubCutoffRegions() const {return nSCoffRegions;};
G4double MeanFreePath(const G4Track& track,
G4double previousStepSize,
@@ -193,31 +233,46 @@ public:
G4double currentMinimumStep,
G4double& currentSafety);
void ResetNumberOfInteractionLengthLeft();
// reset (determine the value of)NumberOfInteractionLengthLeft
protected:
virtual G4double GetMeanFreePath(const G4Track& track,
virtual
G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition);
virtual G4double GetContinuousStepLimit(const G4Track& track,
virtual
G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety);
virtual const G4ParticleDefinition* DefineBaseParticle(
virtual
const G4ParticleDefinition* DefineBaseParticle(
const G4ParticleDefinition*) {return 0;};
virtual G4PhysicsVector* DEDXPhysicsVector(const G4Material*);
virtual
G4PhysicsVector* DEDXPhysicsVector(const G4MaterialCutsCouple*);
virtual G4PhysicsVector* LambdaPhysicsVector(const G4Material*);
virtual
G4PhysicsVector* LambdaPhysicsVector(const G4MaterialCutsCouple*);
virtual G4PhysicsVector* SubLambdaPhysicsVector(const G4Material*);
virtual
G4PhysicsVector* SubLambdaPhysicsVector(const G4MaterialCutsCouple*);
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition*,
const G4Material*, G4double cut) = 0;
virtual G4double MaxSecondaryEnergy(const G4DynamicParticle* dp) = 0;
G4VEmModel* SelectModel(G4double& kinEnergy);
G4VSubCutoffProcessor* SubCutoffProcessor(size_t index);
size_t CurrentMaterialCutsCoupleIndex() const {return currentMaterialIndex;};
void SetMassRatio(G4double val) {massRatio = val;};
void SetReduceFactor(G4double val) {reduceFactor = val;};
@@ -226,19 +281,13 @@ protected:
void SetChargeSquareRatio(G4double val) {chargeSqRatio = val;};
void SetSubCutoffIsDesired(G4bool val);
private:
void Clear();
void DefineMaterial(const G4Material* material);
void DefineMaterial(const G4MaterialCutsCouple* couple);
G4PhysicsTable* BuildLambdaTable();
G4PhysicsTable* BuildLambdaSubTable();
// hide assignment operator
// hide assignment operator
G4VEnergyLossSTD(G4VEnergyLossSTD &);
G4VEnergyLossSTD & operator=(const G4VEnergyLossSTD &right);
@@ -247,9 +296,11 @@ private:
private:
G4EmModelManager* modelManager;
G4VSubCutoffProcessor* subCutoffProcessor;
G4VEmFluctuationModel* emFluctModel;
G4EmModelManager* modelManager;
G4std::vector<G4VSubCutoffProcessor*> scoffProcessors;
G4std::vector<const G4Region*> scoffRegions;
G4int nSCoffRegions;
G4std::vector<G4int> idxSCoffRegions;
// tables and vectors
G4PhysicsTable* theDEDXTable;
@@ -257,33 +308,32 @@ private:
G4PhysicsTable* theSecondaryRangeTable;
G4PhysicsTable* theInverseRangeTable;
G4PhysicsTable* theLambdaTable;
G4PhysicsTable* theSubLambdaTable;
const G4DataVector* theCuts;
G4double minKinEnergy;
G4double maxKinEnergy;
G4int nDEDXBins;
G4int nLambdaBins;
const G4ParticleDefinition* particle;
const G4ParticleDefinition* baseParticle;
const G4ParticleDefinition* secondaryParticle;
const G4ParticleDefinition* theGamma;
const G4ParticleDefinition* theElectron;
// cash
const G4Material* currentMaterial;
const G4MaterialCutsCouple* currentCouple;
size_t currentMaterialIndex;
G4int nDEDXBins;
G4int nLambdaBins;
G4double minKinEnergy;
G4double maxKinEnergy;
G4double massRatio;
G4double reduceFactor;
G4double chargeSquare;
G4double chargeSqRatio;
G4bool lossFluctuationFlag;
G4bool subCutoffFlag;
G4bool subCutoffIsDesired;
G4bool rndmStepFlag;
G4bool hasRestProcess;
G4bool tablesAreBuilt;
G4bool integral;
G4double preStepLambda;
G4double fRange;
G4double preStepKinEnergy;
@@ -291,63 +341,58 @@ private:
G4double linLossLimit;
G4double minSubRange;
G4double dRoverRange;
//G4double maxFinalStep;
G4double finalRange;
G4double c1lim;
G4double c2lim;
G4double c3lim;
// cash
const G4Material* currentMaterial;
G4int currentMaterialIndex;
G4bool lossFluctuationFlag;
G4bool rndmStepFlag;
G4bool hasRestProcess;
G4bool tablesAreBuilt;
G4bool integral;
G4bool meanFreePath;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4bool G4VEnergyLossSTD::IsApplicable(const G4ParticleDefinition& p)
inline void G4VEnergyLossSTD::DefineMaterial(const G4MaterialCutsCouple* couple)
{
return (p.GetPDGCharge() != 0.0);
// G4cout << "couple= " << couple << " currentCouple= " << currentCouple << G4endl;
if(couple != currentCouple) {
currentCouple = couple;
currentMaterial = couple->GetMaterial();
currentMaterialIndex = couple->GetIndex();
if(integral && !meanFreePath) ResetNumberOfInteractionLengthLeft();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::DefineMaterial(const G4Material* material)
inline G4double G4VEnergyLossSTD::GetDEDX(G4double& kineticEnergy,
const G4MaterialCutsCouple* couple)
{
if(material != currentMaterial) {
currentMaterial = material;
currentMaterialIndex = material->GetIndex();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::GetDEDX(G4double kineticEnergy,
const G4Material* material)
{
DefineMaterial(material);
DefineMaterial(couple);
G4bool b;
return ((*theDEDXTable)[currentMaterialIndex]->
GetValue(kineticEnergy*massRatio, b))*chargeSqRatio;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::GetRange(G4double kineticEnergy,
const G4Material* material)
inline G4double G4VEnergyLossSTD::GetRange(G4double& kineticEnergy,
const G4MaterialCutsCouple* couple)
{
DefineMaterial(material);
DefineMaterial(couple);
G4bool b;
return ((*theRangeTable)[currentMaterialIndex]->
GetValue(kineticEnergy*massRatio, b))*reduceFactor;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::GetKineticEnergy(G4double range,
const G4Material* material)
inline G4double G4VEnergyLossSTD::GetKineticEnergy(G4double& range,
const G4MaterialCutsCouple* couple)
{
DefineMaterial(material);
DefineMaterial(couple);
G4bool b;
return ((*theInverseRangeTable)[currentMaterialIndex]->
GetValue(range/reduceFactor, b))/massRatio;
@@ -355,26 +400,38 @@ inline G4double G4VEnergyLossSTD::GetKineticEnergy(G4double range,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetSubCutoffIsDesired(G4bool val)
inline G4double G4VEnergyLossSTD::GetDEDXDispersion(
const G4MaterialCutsCouple *couple,
const G4DynamicParticle* dp,
G4double& length)
{
subCutoffIsDesired = val;
DefineMaterial(couple);
G4double tmax = MaxSecondaryEnergy(dp);
tmax = G4std::min(tmax,(*theCuts)[currentMaterialIndex]);
return modelManager->GetDEDXDispersion(currentMaterial, dp, tmax, length,
currentMaterialIndex);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition* cond)
{
G4bool b;
*cond = NotForced;
DefineMaterial(track.GetMaterial());
DefineMaterial(track.GetMaterialCutsCouple());
preStepKinEnergy = track.GetKineticEnergy();
preStepLambda = (((*theLambdaTable)[currentMaterialIndex])->
GetValue(preStepKinEnergy, b)) * chargeSqRatio;
preStepScaledEnergy = preStepKinEnergy*massRatio;
if (meanFreePath) {
G4bool b;
preStepLambda = (((*theLambdaTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b)) * chargeSqRatio;
if (integral) meanFreePath = false;
}
G4double x = DBL_MAX;
if(0.0 < preStepLambda) x = 1.0/preStepLambda;
// G4cout << GetProcessName() << ": e= " << preStepKinEnergy << " mfp= " << x << G4endl;
return x;
}
@@ -384,137 +441,132 @@ inline G4double G4VEnergyLossSTD::GetContinuousStepLimit(const G4Track&,
G4double, G4double, G4double&)
{
G4double x = DBL_MAX;
preStepScaledEnergy = preStepKinEnergy*massRatio;
if(theRangeTable) {
G4bool b;
if (theRangeTable) {
G4bool b;
fRange = ((*theRangeTable)[currentMaterialIndex])->
GetValue(preStepScaledEnergy, b)*reduceFactor;
if(integral || fRange <= finalRange) {
x = fRange;
GetValue(preStepScaledEnergy, b)*reduceFactor;
x = fRange;
} else {
x = c1lim*fRange+c2lim+c3lim/fRange;
if(rndmStepFlag) x = finalRange + (x-finalRange)*G4UniformRand();
if(x > fRange) x = fRange;
if( !integral ) {
G4double r = G4std::min(finalRange, currentCouple->GetProductionCuts()
->GetProductionCut(idxG4ElectronCut));
if (fRange > r) {
x = dRoverRange*fRange + r*(1.0 - dRoverRange)*(2.0 - r/fRange);
if(rndmStepFlag) x = r + (x-r)*G4UniformRand();
if(x > fRange) x = fRange;
}
}
}
return x;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetParticle(const G4ParticleDefinition* p)
inline void G4VEnergyLossSTD::ResetNumberOfInteractionLengthLeft()
{
particle = p;
if(!baseParticle) baseParticle = DefineBaseParticle(particle);
}
meanFreePath = true;
G4VProcess::ResetNumberOfInteractionLengthLeft();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetBaseParticle(const G4ParticleDefinition* p)
inline G4VEmModel* G4VEnergyLossSTD::SelectModel(G4double& kinEnergy)
{
baseParticle = p;
}
return modelManager->SelectModel(kinEnergy, currentMaterialIndex);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetSecondaryParticle(const G4ParticleDefinition* p)
{
secondaryParticle = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4ParticleDefinition* G4VEnergyLossSTD::Particle() const
inline const G4ParticleDefinition* G4VEnergyLossSTD::Particle() const
{
return particle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4ParticleDefinition* G4VEnergyLossSTD::BaseParticle() const
inline const G4ParticleDefinition* G4VEnergyLossSTD::BaseParticle() const
{
return baseParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline const G4ParticleDefinition* G4VEnergyLossSTD::SecondaryParticle() const
inline const G4ParticleDefinition* G4VEnergyLossSTD::SecondaryParticle() const
{
return secondaryParticle;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetDEDXBinning(G4int nbins)
inline void G4VEnergyLossSTD::SetDEDXBinning(G4int nbins)
{
nDEDXBins = nbins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4int G4VEnergyLossSTD::DEDXBinning() const
inline G4int G4VEnergyLossSTD::DEDXBinning() const
{
return nDEDXBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetLambdaBinning(G4int nbins)
inline void G4VEnergyLossSTD::SetLambdaBinning(G4int nbins)
{
nLambdaBins = nbins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4int G4VEnergyLossSTD::LambdaBinning() const
inline G4int G4VEnergyLossSTD::LambdaBinning() const
{
return nLambdaBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetMinKinEnergy(G4double e)
inline void G4VEnergyLossSTD::SetMinKinEnergy(G4double e)
{
minKinEnergy = e;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::MinKinEnergy() const
inline G4double G4VEnergyLossSTD::MinKinEnergy() const
{
return minKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetMaxKinEnergy(G4double e)
{
inline void G4VEnergyLossSTD::SetMaxKinEnergy(G4double e)
{
maxKinEnergy = e;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::MaxKinEnergy() const
inline G4double G4VEnergyLossSTD::MaxKinEnergy() const
{
return maxKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VEnergyLossSTD::GetLambda(G4double kineticEnergy,
const G4Material* material)
inline G4double G4VEnergyLossSTD::GetLambda(G4double kineticEnergy,
const G4MaterialCutsCouple* couple)
{
DefineMaterial(material);
DefineMaterial(couple);
G4double x = DBL_MAX;
G4bool b;
if(theLambdaTable) {
G4double y = (((*theLambdaTable)[currentMaterialIndex])->
GetValue(kineticEnergy, b));
GetValue(kineticEnergy*massRatio, b));
if(y > 0.0) x = 1.0/y;
}
return x;
@@ -522,18 +574,13 @@ inline G4double G4VEnergyLossSTD::GetLambda(G4double kineticEnergy,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VEnergyLossSTD::SetStepLimits(G4double v1, G4double v2)
inline G4VSubCutoffProcessor* G4VEnergyLossSTD::SubCutoffProcessor(size_t index)
{
dRoverRange = v1;
finalRange = v2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
G4VSubCutoffProcessor* p = 0;
if( nSCoffRegions ) p = scoffProcessors[idxSCoffRegions[index]];
return p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -0,0 +1,416 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class header file
//
//
// File name: G4VMultipleScattering
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 12.03.2002
//
// Modifications:
//
//
// Class Description:
//
// It is the generic process of multiple scattering it includes common
// part of calculations for all charged particles
// -------------------------------------------------------------------
//
#ifndef G4VMultipleScattering_h
#define G4VMultipleScattering_h 1
#include "G4VContinuousDiscreteProcess.hh"
#include "G4LossTableManager.hh"
#include "globals.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ParticleChangeForMSC.hh"
#include "G4Track.hh"
#include "G4EmModelManager.hh"
class G4Step;
class G4ParticleDefinition;
class G4VEmModel;
class G4DataVector;
class G4Navigator;
class G4PhysicsTable;
class G4PhysicsVector;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class G4VMultipleScattering : public G4VContinuousDiscreteProcess
{
public:
G4VMultipleScattering(const G4String& name = "msc",
G4ProcessType type = fElectromagnetic);
~G4VMultipleScattering();
virtual G4bool IsApplicable(const G4ParticleDefinition& p) = 0;
// True for all charged particles
virtual void BuildPhysicsTable(const G4ParticleDefinition&);
// Build physics table during initialisation
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&);
G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&);
G4double AlongStepGetPhysicalInteractionLength(
const G4Track&,
G4double previousStepSize,
G4double currentMinimalStep,
G4double& currentSafety,
G4GPILSelection* selection);
// The function overloads the corresponding function of the base
// class.It limits the step near to boundaries only
// and invokes the method GetContinuousStepLimit at every step.
virtual void PrintInfoDefinition() const;
// Print out of the class parameters
void SetBinning(G4int nbins);
G4int Binning() const;
// Print out of the class parameters
void SetMinKinEnergy(G4double e);
G4double MinKinEnergy() const;
// Print out of the class parameters
void SetMaxKinEnergy(G4double e);
G4double MaxKinEnergy() const;
// Print out of the class parameters
G4bool StorePhysicsTable(G4ParticleDefinition*,
const G4String& directory,
G4bool ascii = false);
// Store PhysicsTable in a file.
// Return false in case of failure at I/O
G4bool RetrievePhysicsTable(G4ParticleDefinition*,
const G4String& directory,
G4bool ascii);
// Retrieve Physics from a file.
// (return true if the Physics Table can be build by using file)
// (return false if the process has no functionality or in case of failure)
// File name should is constructed as processName+particleName and the
// should be placed under the directory specifed by the argument.
void AddEmModel(G4int, G4VEmModel*, const G4Region* region = 0);
G4double ContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimalStep,
G4double& currentSafety);
// This method does not used for tracking, it is intended only for tests
G4bool LateralDisplasmentFlag() const;
void SetLateralDisplasmentFlag(G4bool val);
// lateral displacement to be/not to be computed
G4bool BoundaryAlgorithmFlag() const;
void SetBoundary(G4bool val);
// boundary algorith is/isnt active
void SetBuildLambdaTable(G4bool val);
virtual G4double TruePathLengthLimit(const G4Track& track,
G4double& lambda,
G4double currentMinimalStep) = 0;
protected:
virtual void InitialiseProcess(const G4ParticleDefinition&) = 0;
G4double GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition* condition);
// This method is used for tracking, it returns mean free path value
G4double GetLambda(const G4ParticleDefinition* p, G4double& kineticEnergy);
G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimalStep,
G4double& currentSafety);
// This method is used for tracking, it returns step limit
virtual G4PhysicsVector* PhysicsVector(const G4MaterialCutsCouple*);
// Build empty Physics Vector
void SelectModel(G4double& kinEnergy);
// Select concrete model
size_t CurrentMaterialCutsCoupleIndex() const {return currentMaterialIndex;};
// Return current index
G4double CurrentRange() const {return currentRange;};
private:
void DefineMaterial(const G4MaterialCutsCouple* couple);
// define current material
// hide assignment operator
G4VMultipleScattering(G4VMultipleScattering &);
G4VMultipleScattering & operator=(const G4VMultipleScattering &right);
// =====================================================================
private:
G4ParticleChangeForMSC fParticleChange;
G4EmModelManager* modelManager;
G4Navigator* navigator;
G4VEmModel* currentModel;
// tables and vectors
G4PhysicsTable* theLambdaTable;
// cash
const G4Material* currentMaterial;
const G4MaterialCutsCouple* currentCouple;
size_t currentMaterialIndex;
G4int nBins;
G4double minKinEnergy;
G4double maxKinEnergy;
G4double trueStepLength;
G4double truePathLength;
G4double geomPathLength;
G4double lambda0;
G4double currentRange;
G4GPILSelection valueGPILSelectionMSC;
G4bool boundary;
G4bool latDisplasment;
G4bool buildLambdaTable;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::DefineMaterial(const G4MaterialCutsCouple* couple)
{
if(couple != currentCouple) {
currentCouple = couple;
currentMaterial = couple->GetMaterial();
currentMaterialIndex = couple->GetIndex();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition* cond)
{
*cond = Forced;
return DBL_MAX;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4double currentMinimalStep,
G4double& currentSafety,
G4GPILSelection* selection)
{
// get Step limit proposed by the process
valueGPILSelectionMSC = NotCandidateForSelection;
G4double steplength = GetContinuousStepLimit(track,previousStepSize,
currentMinimalStep,currentSafety);
// set return value for G4GPILSelection
*selection = valueGPILSelectionMSC;
return steplength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::GetContinuousStepLimit(
const G4Track& track,
G4double,
G4double currentMinimalStep,
G4double&)
{
DefineMaterial(track.GetMaterialCutsCouple());
G4double e = track.GetKineticEnergy();
SelectModel(e);
const G4ParticleDefinition* p = track.GetDefinition();
lambda0 = GetLambda(p, e);
currentRange = G4LossTableManager::Instance()->GetRange(p,e,currentCouple);
truePathLength = TruePathLengthLimit(track,lambda0,currentMinimalStep);
//G4cout << "StepLimit: tpl= " << truePathLength << " lambda0= "
// << lambda0 << " range= " << currentRange
// << " currentMinStep= " << currentMinimalStep << G4endl;
if (truePathLength < currentMinimalStep) valueGPILSelectionMSC = CandidateForSelection;
geomPathLength = currentModel->GeomPathLength(theLambdaTable,currentCouple,
p,e,lambda0,currentRange,truePathLength);
if(geomPathLength > lambda0) geomPathLength = lambda0;
return geomPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::ContinuousStepLimit(
const G4Track& track,
G4double previousStepSize,
G4double currentMinimalStep,
G4double& currentSafety)
{
return GetContinuousStepLimit(track,previousStepSize,currentMinimalStep,
currentSafety);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::GetLambda(const G4ParticleDefinition* p, G4double& e)
{
G4double x;
if(theLambdaTable) {
G4bool b;
x = ((*theLambdaTable)[currentMaterialIndex])->GetValue(e, b);
} else {
x = currentModel->CrossSection(currentMaterial,p,e,0.0,1.0);
}
return x;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4VParticleChange* G4VMultipleScattering::AlongStepDoIt(
const G4Track& track,
const G4Step& step)
{
fParticleChange.Initialize(track);
G4double geomStepLength = step.GetStepLength();
if (geomStepLength == geomPathLength) trueStepLength = truePathLength;
else trueStepLength = currentModel->TrueStepLength(geomStepLength);
fParticleChange.SetTrueStepLength(trueStepLength);
// G4cout << "AlongStep: trueLength= " << trueStepLength << " geomLength= "<< geomStepLength << " zlast= " << geomPathLength << G4endl;
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SelectModel(G4double& kinEnergy)
{
currentModel = modelManager->SelectModel(kinEnergy, currentMaterialIndex);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetBinning(G4int nbins)
{
nBins = nbins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4int G4VMultipleScattering::Binning() const
{
return nBins;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetMinKinEnergy(G4double e)
{
minKinEnergy = e;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::MinKinEnergy() const
{
return minKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetMaxKinEnergy(G4double e)
{
maxKinEnergy = e;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4double G4VMultipleScattering::MaxKinEnergy() const
{
return maxKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4bool G4VMultipleScattering::LateralDisplasmentFlag() const
{
return latDisplasment;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetLateralDisplasmentFlag(G4bool val)
{
latDisplasment = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline G4bool G4VMultipleScattering::BoundaryAlgorithmFlag() const
{
return boundary;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetBoundary(G4bool val)
{
boundary = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4VMultipleScattering::SetBuildLambdaTable(G4bool val)
{
buildLambdaTable = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -34,7 +34,11 @@
//
// Modifications:
//
// Class Description:
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 29-12-02 Change interface (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// Abstract class for interface to simualtion of subCutoff
@@ -51,30 +55,34 @@
class G4Step;
class G4Track;
class G4ParticleDefinition;
class G4DynamicParticle;
class G4EmModelManager;
class G4VEmModel;
class G4DataVector;
class G4PhysicsTable;
class G4VSubCutoffProcessor
class G4VSubCutoffProcessor
{
public:
G4VSubCutoffProcessor() {};
G4VSubCutoffProcessor(const G4String& nam): name(nam) {};
virtual ~G4VSubCutoffProcessor() {};
virtual G4std::vector<G4Track*>* SampleSecondary(const G4Step& step,
const G4DynamicParticle*,
G4double meanLoss) {return 0;};
virtual G4std::vector<G4Track*>* SampleSecondaries(const G4Step&,
G4double& tmax,
G4double& meanLoss,
G4VEmModel*) = 0;
virtual void Initialise(const G4ParticleDefinition*,
const G4ParticleDefinition*,
G4EmModelManager* ) {};
virtual void Initialise(const G4ParticleDefinition*,
const G4ParticleDefinition*,
const G4DataVector*,
const G4DataVector*) = 0;
virtual void SetLambdaSubTable(G4PhysicsTable*) {};
virtual void SetLambdaSubTable(G4PhysicsTable*) = 0;
virtual G4PhysicsTable* LambdaSubTable() {return 0;};
virtual G4PhysicsTable* LambdaSubTable() = 0;
G4String GetName() const {return name;};
protected:
@@ -84,6 +92,7 @@ private:
G4VSubCutoffProcessor & operator=(const G4VSubCutoffProcessor &right);
G4VSubCutoffProcessor(const G4VSubCutoffProcessor&);
const G4String name;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -29,10 +29,15 @@
// File name: G4BetheBlochModel
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
//
// Creation date: 03.01.2002
//
// Modifications: 04.12.2002 VI Fix problem of G4DynamicParticle constructor
// Modifications:
//
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
@@ -47,13 +52,13 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p)
: G4VEmModel(),
G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),
particle(0),
highKinEnergy(100.*TeV),
lowKinEnergy(2.0*MeV),
twoln10(2.0*log(10.0)),
bg2lim(0.0169),
bg2lim(0.0169),
taulim(8.4146e-3)
{
if(p) SetParticle(p);
@@ -61,12 +66,12 @@ G4BetheBlochModel::G4BetheBlochModel(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BetheBlochModel::~G4BetheBlochModel()
G4BetheBlochModel::~G4BetheBlochModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
@@ -80,17 +85,15 @@ void G4BetheBlochModel::SetParticle(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BetheBlochModel::HighEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
@@ -99,32 +102,39 @@ G4double G4BetheBlochModel::LowEnergyLimit(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
const G4MaterialCutsCouple* couple)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
G4bool G4BetheBlochModel::IsInCharge(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BetheBlochModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
if(!particle) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BetheBlochModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
G4double cutEnergy)
{
if(!particle) SetParticle(p);
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double tau = kineticEnergy/mass;
G4double x = 1.0;
if(cutEnergy < tmax) x = cutEnergy/tmax;
G4double gam = tau + 1.0;
G4double gam = tau + 1.0;
G4double beta2 = 1. - 1./(gam*gam);
G4double bg2 = tau * (tau+2.0);
@@ -190,24 +200,23 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
G4double cutEnergy,
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
G4double x = cutEnergy/tmax;
G4double energy = kineticEnergy + mass;
G4double gam = energy/mass;
G4double beta2 = 1. - 1./(gam*gam);
cross = (1.0 - x*(1.0 - beta2*log(x)))/cutEnergy;
// +term for spin=1/2 particle
if( 0.5 == spin ) {
cross += 0.5 * (tmax - cutEnergy) / (energy*energy);
// +term for spin=1 particle
} else if( 0.9 < spin ) {
cross += -log(x)/(3.0*qc) +
(tmax - cutEnergy) * ((1.0+ 0.25*tmax*(1.0 + x)/qc)/(energy*energy)
- beta2 / (tmax * qc) )/3.0;
@@ -222,11 +231,11 @@ G4double G4BetheBlochModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
const G4Material* material,
G4DynamicParticle* G4BetheBlochModel::SampleSecondary(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
@@ -253,7 +262,7 @@ G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
}
G4double z, f;
// sampling follows ...
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
@@ -267,34 +276,48 @@ G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondary(
G4cout << "G4BetheBlochModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
<< G4endl;
}
} while( grej*G4UniformRand() > f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta = new G4DynamicParticle();
delta->SetDefinition(G4Electron::Electron());
delta->SetKineticEnergy(deltaKinEnergy);
delta->SetMomentumDirection(deltaDirection);
return delta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BetheBlochModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,112 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4BohrFluctuations
//
// Author: Vladimir Ivanchenko
//
// Creation date: 02.04.2003
//
// Modifications:
//
//
// Class Description: Sampling of Gaussion fluctuations
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4BohrFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BohrFluctuations::G4BohrFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
minFraction(0.2)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BohrFluctuations::~G4BohrFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BohrFluctuations::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BohrFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
// Gaussian fluctuation
if (meanLoss >= minNumberInteractionsBohr*tmax) {
// Increase fluctuations for big fractional energy loss
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
loss = meanLoss*n/navr;
}
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -32,12 +32,17 @@
//
// Creation date: 03.01.2002
//
// Modifications: 04.12.2002 VI Fix problem of G4DynamicParticle constructor
// Modifications:
//
// Class Description:
// 04-12-02 Fix problem of G4DynamicParticle constructor (V.Ivanchenko)
// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
// Class Description:
//
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// Implementation of energy loss and delta-electron production by
// slow charged heavy particles
// -------------------------------------------------------------------
//
@@ -52,8 +57,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p)
: G4VEmModel(),
G4BraggModel::G4BraggModel(const G4ParticleDefinition* p, const G4String& nam)
: G4VEmModel(nam),
particle(0),
highKinEnergy(2.0*MeV),
lowKinEnergy(0.0*MeV),
@@ -66,12 +71,12 @@ G4BraggModel::G4BraggModel(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BraggModel::~G4BraggModel()
G4BraggModel::~G4BraggModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
{
particle = p;
mass = particle->GetPDGMass();
@@ -85,17 +90,15 @@ void G4BraggModel::SetParticle(const G4ParticleDefinition* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BraggModel::HighEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return highKinEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p,
const G4Material*)
G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return lowKinEnergy;
@@ -104,27 +107,34 @@ G4double G4BraggModel::LowEnergyLimit(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::MinEnergyCut(const G4ParticleDefinition* p,
const G4Material* material)
const G4MaterialCutsCouple* couple)
{
return material->GetIonisation()->GetMeanExcitationEnergy();
return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p,
const G4Material*)
G4bool G4BraggModel::IsInCharge(const G4ParticleDefinition* p)
{
if(!particle) SetParticle(p);
return (p->GetPDGCharge() != 0.0 && p->GetPDGMass() > 10.*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BraggModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
if(!particle) SetParticle(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BraggModel::ComputeDEDX(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy)
G4double cutEnergy)
{
if(!particle) SetParticle(p);
G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
G4double dedx = DEDX(material, kineticEnergy/massRate);
@@ -133,20 +143,20 @@ G4double G4BraggModel::ComputeDEDX(const G4Material* material,
G4double x = cutEnergy/tmax;
G4double tau = kineticEnergy/mass;
G4double gam = tau + 1.0;
G4double gam = tau + 1.0;
G4double beta2 = 1. - 1./(gam*gam);
// G4double bg2 = tau * (tau+2.0);
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
// G4double bg2 = tau * (tau+2.0);
dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2
* (material->GetElectronDensity())/beta2;
}
}
// now compute the total ionization loss
if (dedx < 0.0) dedx = 0.0 ;
dedx *= chargeSquare;
return dedx;
return dedx;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -155,9 +165,9 @@ G4double G4BraggModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double cutEnergy,
G4double maxEnergy)
G4double maxEnergy)
{
if(!particle) SetParticle(p);
G4double cross = 0.0;
G4double tmax = G4std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
if(cutEnergy < tmax) {
@@ -177,11 +187,11 @@ G4double G4BraggModel::CrossSection(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
const G4Material* material,
G4DynamicParticle* G4BraggModel::SampleSecondary(
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
G4double maxEnergy)
{
G4double tmax = MaxSecondaryEnergy(dp);
G4double xmin = tmin/tmax;
@@ -193,10 +203,10 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
G4double beta2 = 1. - mass*mass/(energy*energy);
G4double grej = 1.0 - beta2*xmin;
G4double z, f;
G4ThreeVector momentum = dp->GetMomentumDirection();
// sampling follows ...
// sampling follows ...
do {
G4double q = G4UniformRand();
z = xmin*xmax/(xmin*(1.0 - q) + xmax*q);
@@ -207,21 +217,21 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
G4cout << "G4BraggModel::SampleSecondary Warning! "
<< "Majorant " << grej << " < "
<< f << " for x= " << z
<< G4endl;
<< G4endl;
}
} while( grej*G4UniformRand() >= f );
G4double deltaKinEnergy = z * tmax;
G4double deltaMomentum =
G4double deltaMomentum =
sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
G4double totMomentum = sqrt(energy*energy - mass*mass);
G4double cost = deltaKinEnergy * (energy + electron_mass_c2) /
(deltaMomentum * totMomentum);
G4double sint = sqrt(1.0 - cost*cost);
G4double phi = twopi * G4UniformRand() ;
G4double phi = twopi * G4UniformRand() ;
G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ;
deltaDirection.rotateUz(momentum);
@@ -232,7 +242,19 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
delta->SetKineticEnergy(deltaKinEnergy);
delta->SetMomentumDirection(deltaDirection);
return delta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondaries(
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double tmin,
G4double maxEnergy)
{
G4std::vector<G4DynamicParticle*>* vdp = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* delta = SampleSecondary(couple, dp, tmin, maxEnergy);
vdp->push_back(delta);
return vdp;
@@ -240,7 +262,7 @@ G4std::vector<G4DynamicParticle*>* G4BraggModel::SampleSecondary(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BraggModel::HasMaterial(const G4Material* material)
G4bool G4BraggModel::HasMaterial(const G4Material* material)
{
G4String chFormula = material->GetChemicalFormula() ;
G4String myFormula = G4String(" ") ;
@@ -251,10 +273,10 @@ G4bool G4BraggModel::HasMaterial(const G4Material* material)
}
// ICRU Report N49, 1993. Power's model for He.
const size_t numberOfMolecula = 11 ;
const size_t numberOfMolecula = 11 ;
static G4String name[numberOfMolecula] = {
"Al_2O_3", "CO_2", "CH_4",
"(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polypropylene", "(C_8H_8)_N",
"Al_2O_3", "CO_2", "CH_4",
"(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polypropylene", "(C_8H_8)_N",
"C_3H_8", "SiO_2", "H_2O",
"H_2O-Gas", "Graphite" } ;
@@ -335,7 +357,7 @@ G4double G4BraggModel::StoppingPower(const G4Material* material,
}
return ionloss;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -655,7 +677,7 @@ G4double G4BraggModel::ChemicalFactor(G4double kineticEnergy,
G4double factor = 1.0 + (expStopPower125/eloss125 - 1.0) *
(1.0 + exp( 1.48 * ( beta125/beta25 - 7.0 ) ) ) /
(1.0 + exp( 1.48 * ( beta/beta25 - 7.0 ) ) ) ;
return factor ;
}
@@ -28,15 +28,23 @@
//
// File name: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 23-12-02 V.Ivanchenko change interface in order to move
// to cut per region
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 24-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 The set of models is defined for region (V.Ivanchenko)
// 06-03-03 Fix in energy intervals for models (V.Ivanchenko)
// 13-04-03 Add startFromNull (V.Ivanchenko)
//
// It is the unified energy loss process it calculates the continuous
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
@@ -45,41 +53,88 @@
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EmModelManager.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsVector.hh"
#include "G4VParticleChange.hh"
#include "G4Gamma.hh"
#include "G4Positron.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::G4RegionModels(G4int nMod, G4std::vector<G4int>& list, G4DataVector& lowE)
{
nModelsForRegion = nMod;
theListOfModelIndexes = new G4int [nModelsForRegion];
lowKineticEnergy = new G4double [nModelsForRegion];
for (G4int i=0; i<nModelsForRegion; i++) {
theListOfModelIndexes[i] = list[i];
lowKineticEnergy[i] = lowE[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::~G4RegionModels()
{
delete [] theListOfModelIndexes;
delete [] lowKineticEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::G4EmModelManager():
nEmModels(0),
nmax(4),
orderIsChanged(false),
nRegions(0),
nCouples(0),
minSubRange(0.1),
particle(0)
particle(0),
verboseLevel(0)
{
verboseLevel = 0;
for(G4int i = 0; i<nmax; i++) {
emModels[i] = 0;
order[i] = 0;
upperEkin[i] = 0.0;
}
models.clear();
flucModels.clear();
regions.clear();
orderOfModels.clear();
upperEkin.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::~G4EmModelManager()
{
G4int i,j;
Clear();
for(G4int i = 0; i<nmax; i++) {
if(emModels[i]) delete emModels[i];
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(models[i] == models[j]) orderOfModels[j] = 0;
}
delete models[i];
}
}
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(flucModels[i] == flucModels[j]) orderOfModels[j] = 0;
}
delete flucModels[i];
}
}
}
@@ -93,18 +148,52 @@ void G4EmModelManager::Clear()
theCuts.clear();
theSubCuts.clear();
upperEkin.clear();
idxOfRegionModels.clear();
setOfRegionModels.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
G4VEmFluctuationModel* fm, const G4Region* r)
{
if(!p) {
G4cout << "G4EmModelManager::AddEmModel WARNING: no model defined." << G4endl;
return;
}
models.push_back(p);
flucModels.push_back(fm);
regions.push_back(r);
orderOfModels.push_back(num);
if (nEmModels) {
G4int idx = nEmModels;
do {idx--;} while (idx && num < orderOfModels[idx]);
if (num >= orderOfModels[idx] && num <= orderOfModels[idx+1]) idx++;
if (idx < nEmModels) {
models[nEmModels] = models[idx];
flucModels[nEmModels] = flucModels[idx];
regions[nEmModels] = regions[idx];
orderOfModels[nEmModels] = orderOfModels[idx];
models[idx] = p;
flucModels[idx] = fm;
regions[idx] = r;
orderOfModels[idx] = num;
}
}
nEmModels++;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4double theMinSubRange,
G4int val)
{
// Are models defined?
if(!nEmModels) {
G4Exception("G4EmModelManager::Initialise without any model defined");
G4Exception("G4EmModelManager::Initialise without any model defined");
}
particle = p;
secondaryParticle = sp;
@@ -112,188 +201,161 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
verboseLevel = val;
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< p->GetParticleName()
G4cout << "### G4EmModelManager::Initialise() for "
<< p->GetParticleName()
<< G4endl;
}
Clear();
// Ordering
if(orderIsChanged) {
G4int oldOrder[5];
G4VEmModel* oldEmModels[5];
for(G4int k = 0; k<nmax; k++) {
oldEmModels[k] = emModels[k];
oldOrder[k] = order[k];
}
G4RegionStore* regionStore = G4RegionStore::GetInstance();
const G4Region* world = regionStore->GetRegion("DefaultRegionForTheWorld", false);
// Identify the list of regions with different set of models
nRegions = 1;
G4std::vector<const G4Region*> set;
set.push_back(world);
for(G4int ik=0; ik<nEmModels; ik++) {
G4int low = INT_MAX;
G4int index = 0;
for(G4int kk=0; kk<nEmModels; kk++) {
if(oldEmModels[kk]) {
if(oldOrder[kk] < low) {
low = oldOrder[kk];
index = kk;
}
}
for (G4int ii=0; ii<nEmModels; ii++) {
const G4Region* r = regions[ii];
if ( r && r != world) {
G4bool newRegion = true;
if (nRegions>1) {
for (G4int j=1; j<nRegions; j++) {
if ( r == set[j] ) newRegion = false;
}
}
if (newRegion) {
set.push_back(r);
nRegions++;
}
emModels[ik] = oldEmModels[index];
order[ik] = ik;
oldEmModels[index] = 0;
}
orderIsChanged = false;
}
G4DataVector eLow;
eLow.clear();
setOfRegionModels.clear();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
idxOfRegionModels.resize(numOfCouples);
upperEkin.resize(nEmModels);
G4int n = 0;
// Order models for regions
for (G4int reg=0; reg<nRegions; reg++) {
for(G4int j=0; j<nEmModels; j++) {
const G4Region* region = set[reg];
G4double ep = 0.0;
if(0 < n) ep = upperEkin[n-1];
G4VEmModel* model = emModels[j];
G4bool accepted = false;
G4int n = 0;
if(model->IsInCharge(particle, 0)) {
G4std::vector<G4int> modelAtRegion;
G4DataVector eLow;
G4DataVector eHigh;
modelAtRegion.clear();
eLow.clear();
eHigh.clear();
G4double tmin = model->LowEnergyLimit(particle, 0);
G4double tmax = model->HighEnergyLimit(particle, 0);
for (G4int ii=0; ii<nEmModels; ii++) {
if(1 < verboseLevel) {
G4cout << "New model for tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
G4VEmModel* model = models[ii];
if ( (model->IsInCharge(particle)) &&
(0 == regions[ii] || region == regions[ii]) )
{
G4double tmin = model->LowEnergyLimit(particle);
G4double tmax = model->HighEnergyLimit(particle);
if (n) tmin = G4std::max(tmin, eHigh[n-1]);
if(1 < verboseLevel) {
G4cout << "Model # " << ii << " for region <"
<< region->GetName() << "> "
<< " tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< G4endl;
}
}
if(tmax > tmin) {
if(n == 0 || tmax > upperEkin[n-1]) {
// First model or next model for more high energy range;
upperEkin[n] = (tmax);
if(0 < n) tmin = G4std::max(tmin, upperEkin[n-1]);
eLow.push_back(tmin);
n++;
accepted = true;
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
<< G4endl;
if (tmin < tmax) {
modelAtRegion.push_back(ii);
eLow.push_back(tmin);
eHigh.push_back(tmax);
upperEkin[ii] = tmax;
n++;
}
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< G4endl;
}
}
if(!accepted) {
upperEkin[n] = ep;
eLow.push_back(ep);
n++;
eLow[0] = 0.0;
if(1 < verboseLevel) {
G4cout << "New G4RegionModels set with " << n << " models for region <"
<< region->GetName() << "> " << G4endl;
}
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow);
setOfRegionModels.push_back(rm);
}
// Access to materials and build cuts
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
for(size_t i=0; i<numOfCouples; i++) {
for(size_t i=0; i<nMaterials; i++) {
const G4Material* material = (*theMaterialTable)[i];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ProductionCuts* pcuts = couple->GetProductionCuts();
G4int reg = nRegions;
do {reg--;} while (reg>0 && pcuts != (set[reg]->GetProductionCuts()));
idxOfRegionModels[i] = reg;
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
G4cout << "G4EmModelManager::Initialise() for "
<< material->GetName() << G4endl;
}
G4double cut = 0.0;
G4double subcut = 0.0;
if(secondaryParticle) {
cut = secondaryParticle->GetEnergyThreshold(material);
size_t idx = 1;
if( secondaryParticle == G4Gamma::Gamma() ) idx = 0;
cut = (*theCoupleTable->GetEnergyCutsVector(idx))[i];
subcut = minSubRange*cut;
}
for(G4int j=0; j<nEmModels; j++) {
G4int nm = setOfRegionModels[reg]->NumberOfModels();
for(G4int j=0; j<nm; j++) {
G4VEmModel* model = emModels[j];
if(upperEkin[j] > eLow[j]) {
G4VEmModel* model = models[setOfRegionModels[reg]->ModelIndex(j)];
G4double tcutmin = model->MinEnergyCut(particle, material);
G4double tcutmin = model->MinEnergyCut(particle, couple);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< G4endl;
}
cut = G4std::max(cut, tcutmin);
subcut = G4std::max(subcut, tcutmin);
cut = G4std::max(cut, tcutmin);
G4double x = G4std::max(cut*minSubRange, tcutmin);
subcut = G4std::max(subcut, x);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< "; tcut(MeV)= " << cut/MeV
<< G4endl;
}
}
theCuts.push_back(cut);
theSubCuts.push_back(subcut);
}
if(1 < verboseLevel) {
G4cout << "G4EmModelManager is initialised "
<< G4endl;
}
return &theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::AddEmModel(G4VEmModel* p, G4int num)
{
if(nEmModels) {
for(G4int i=0; i<nEmModels; i++) {
if(num < order[i]) orderIsChanged = true;
}
for(G4int jj=0; jj<nEmModels; jj++) {
models[jj]->Initialise(particle, theCuts);
if(flucModels[jj]) flucModels[jj]->Initialise(particle);
}
if(nEmModels == nmax) {
G4cout << "G4EmModelManager::AddEmModel WARNING: cannot accept model #"
<< nEmModels << " - the list is closed"
<< G4endl;
} else {
emModels[nEmModels] = p;
order[nEmModels] = num;
currentModel = p;
nEmModels++;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
G4cout << "G4EmModelManager is initialised "
<< G4endl;
}
return &theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple)
{
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
@@ -301,42 +363,59 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
const G4Material* material = couple->GetMaterial();
size_t i = couple->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
dedxLow.resize(nEmModels);
dedxHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
<< " Ecut(MeV)= " << cut/MeV
<< G4endl;
}
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
dedxLow.resize(nmod);
dedxHigh.resize(nmod);
if(0 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
<< material->GetName()
<< " at the region #" << reg
<< G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLoss = aVector->GetVectorLength();
dedxLow[0] = 0.0;
e = upperEkin[0];
dedxHigh[0] = emModels[0]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[regModels->ModelIndex(0)];
dedxHigh[0] = models[regModels->ModelIndex(0)]->ComputeDEDX(material,particle,e,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
for(j=1; j<nmod; j++) {
e = upperEkin[j-1];
dedxLow[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[j];
dedxHigh[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[regModels->ModelIndex(j-1)];
dedxLow[j] = models[regModels->ModelIndex(j)]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[regModels->ModelIndex(j)];
dedxHigh[j] = models[regModels->ModelIndex(j)]->ComputeDEDX(material,particle,e,cut);
}
for(j=1; j<nEmModels; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
for(j=1; j<nmod; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
else factor[j] = 0.0;
}
if(0 < verboseLevel) {
if(1 < verboseLevel) {
G4cout << "Loop over " << totBinsLoss << " bins start " << G4endl;
}
}
@@ -349,22 +428,21 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
// Choose a model of energy losses
G4int k = 0;
if(nEmModels > 1) {
if (e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
G4double dedx = emModels[k]->ComputeDEDX(material,particle,e,cut)*fac;
G4double dedx = models[regModels->ModelIndex(k)]->ComputeDEDX(material,particle,e,cut)*fac;
if(dedx < 0.0) dedx = 0.0;
if(0 < verboseLevel) {
if(1 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " fac= " << fac
<< G4endl;
}
aVector->PutValue(j, dedx);
@@ -374,16 +452,11 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4bool startFromNull)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
@@ -391,14 +464,28 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
const G4Material* material = couple->GetMaterial();
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName()
<< " in " << material->GetName()
<< G4endl;
}
size_t i = couple->GetIndex();
G4double cut = theCuts[i];
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
sigmaLow.resize(nmod);
sigmaHigh.resize(nmod);
if(1 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
<< material->GetName() << G4endl;
}
@@ -409,31 +496,31 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
sigmaLow[0] = 0.0;
e = upperEkin[0];
e = upperEkin[regModels->ModelIndex(0)];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " " << nEmModels
<< " " << nmod
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " Emax(MeV)= " << e/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,cut,e);
if(nEmModels > 1) {
sigmaHigh[0] = models[regModels->ModelIndex(0)]->CrossSection(material,particle,e,cut,e);
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
for(j=1; j<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
sigmaLow[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,cut,e);
e = upperEkin[regModels->ModelIndex(j)];
sigmaHigh[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,cut,e);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
for(j=1; j<nmod; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
@@ -446,30 +533,23 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
// Cross section interpolation should start from zero
G4double cross = 0.0;
if(j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,cut,e)*fac;
}
G4double cross = models[regModels->ModelIndex(k)]->CrossSection(material,particle,e,cut,e)*fac;
if(j==0 && startFromNull) cross = 0.0;
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
G4cout << "FillLambdaVector: " << j << ". e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
// if(cross <= 0.0) cross = DBL_MAX;
// else cross = 1.0/cross;
if(cross < 0.0) cross = 0.0;
aVector->PutValue(j, cross);
}
@@ -477,11 +557,12 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4bool startFromNull)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
<< particle->GetParticleName() << G4endl;
}
@@ -493,15 +574,20 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
G4double e;
G4int i = material->GetIndex();
const G4Material* material = couple->GetMaterial();
size_t i = couple->GetIndex();
G4double cut = theCuts[i];
G4double subcut = theSubCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
sigmaLow.resize(nmod);
sigmaHigh.resize(nmod);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
G4cout << "There are " << nmod << " models for "
<< material->GetName() << G4endl;
}
@@ -512,31 +598,31 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
sigmaLow[0] = 0.0;
e = upperEkin[0];
e = upperEkin[regModels->ModelIndex(0)];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " are available " << nEmModels
<< " are available " << nmod
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,subcut,cut);
if(nEmModels > 1) {
sigmaHigh[0] = models[regModels->ModelIndex(0)]->CrossSection(material,particle,e,subcut,cut);
for(j=1; j<nEmModels; j++) {
if(nmod > 1) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
for(j=1; j<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
sigmaLow[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,subcut,cut);
e = upperEkin[regModels->ModelIndex(j)];
sigmaHigh[j] = models[regModels->ModelIndex(j)]->CrossSection(material,particle,e,subcut,cut);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
for(j=1; j<nmod; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
@@ -549,37 +635,26 @@ void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e < upperEkin[regModels->ModelIndex(k)] );
}
G4double cross = 0.0;
// Cross section interpolation should start from zero
if (j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,subcut,cut)*fac;
}
G4double cross=models[regModels->ModelIndex(k)]->CrossSection(material,particle,e,subcut,cut)*fac;
if(j==0 && startFromNull) cross = 0.0;
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
if(cross < 0.0) cross = 0.0;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,10 +21,10 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.cc,v 1.5 2002/12/04 21:07:43 asaim Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossMessenger.cc,v 1.7 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -32,6 +32,7 @@
#include "G4EnergyLossMessenger.hh"
#include "G4VEnergyLoss.hh"
#include "G4LossTableManager.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
@@ -52,24 +53,24 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
RndmStepCmd->SetParameterName("choice",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(G4State_Idle);
RndmStepCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
EnlossFlucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
EnlossFlucCmd->SetGuidance("Switch true/false the energy loss fluctuations.");
EnlossFlucCmd->SetParameterName("choice",true);
EnlossFlucCmd->SetDefaultValue(true);
EnlossFlucCmd->AvailableForStates(G4State_Idle);
EnlossFlucCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
SubSecCmd = new G4UIcmdWithABool("/process/eLoss/subsec",this);
SubSecCmd->SetGuidance("Switch true/false the subcutoff generation.");
SubSecCmd->SetParameterName("choice",true);
SubSecCmd->SetDefaultValue(true);
SubSecCmd->AvailableForStates(G4State_Idle);
SubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinSubSecCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minsubsec",this);
MinSubSecCmd->SetGuidance("Set the min. cut for subcutoff delta in range.");
MinSubSecCmd->SetParameterName("rcmin",true);
MinSubSecCmd->AvailableForStates(G4State_Idle);
MinSubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
@@ -93,7 +94,25 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(G4State_Idle);
StepFuncCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minKinEnergy",this);
MinEnCmd->SetGuidance("Set the min kinetic energy");
MinEnCmd->SetParameterName("emin",true);
MinEnCmd->SetUnitCategory("Energy");
MinEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MaxEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/maxKinEnergy",this);
MaxEnCmd->SetGuidance("Set the max kinetic energy");
MaxEnCmd->SetParameterName("emax",true);
MaxEnCmd->SetUnitCategory("Energy");
MaxEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
IntegCmd = new G4UIcmdWithABool("/process/eLoss/integral",this);
IntegCmd->SetGuidance("Switch true/false the integration of cross section over step.");
IntegCmd->SetParameterName("integ",true);
IntegCmd->SetDefaultValue(true);
IntegCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -106,22 +125,29 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
delete MinSubSecCmd;
delete StepFuncCmd;
delete eLossDirectory;
delete MinEnCmd;
delete MaxEnCmd;
delete IntegCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
{
G4LossTableManager* lossTables = G4LossTableManager::Instance();
if (command == RndmStepCmd)
{ G4VEnergyLoss::SetRndmStep(RndmStepCmd->GetNewBoolValue(newValue));
lossTables->SetRandomStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd)
{ G4VEnergyLoss::SetEnlossFluc(EnlossFlucCmd->GetNewBoolValue(newValue));
lossTables->SetLossFluctuations(EnlossFlucCmd->GetNewBoolValue(newValue));
}
if (command == SubSecCmd)
{ G4VEnergyLoss::SetSubSec(SubSecCmd->GetNewBoolValue(newValue));
lossTables->SetSubCutoff(SubSecCmd->GetNewBoolValue(newValue));
}
if (command == MinSubSecCmd)
@@ -138,7 +164,20 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
G4VEnergyLoss::SetStepFunction(v1,v2);
lossTables->SetStepLimits(v1,v2);
}
if (command == MinEnCmd) {
lossTables->SetMinEnergy(MinEnCmd->GetNewDoubleValue(newValue));
}
if (command == MaxEnCmd) {
lossTables->SetMaxEnergy(MaxEnCmd->GetNewDoubleValue(newValue));
}
if (command == IntegCmd) {
lossTables->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1,190 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4EnergyLossMessengerSTD
//
// Author:
//
// Creation date:
//
// Modifications:
//
// 03.01.2002 V.Ivanchenko update to new design
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EnergyLossMessengerSTD.hh"
#include "G4LossTableManager.hh"
#include "G4UIdirectory.hh"
#include "G4UIcommand.hh"
#include "G4UIparameter.hh"
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "g4std/strstream"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessengerSTD::G4EnergyLossMessengerSTD()
{
eLossDirectory = new G4UIdirectory("/process/eLoss/");
eLossDirectory->SetGuidance("Commands for G4VEnergyLoss.");
RndmStepCmd = new G4UIcmdWithABool("/process/eLoss/rndmStep",this);
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
RndmStepCmd->SetParameterName("rndmStep",true);
RndmStepCmd->SetDefaultValue(false);
RndmStepCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
EnlossFlucCmd = new G4UIcmdWithABool("/process/eLoss/fluct",this);
EnlossFlucCmd->SetGuidance("Switch true/false the energy loss fluctuations.");
EnlossFlucCmd->SetParameterName("fluct",true);
EnlossFlucCmd->SetDefaultValue(true);
EnlossFlucCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
SubSecCmd = new G4UIcmdWithABool("/process/eLoss/subsec",this);
SubSecCmd->SetGuidance("Switch true/false the subcutoff generation.");
SubSecCmd->SetParameterName("subsec",true);
SubSecCmd->SetDefaultValue(true);
SubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
IntegCmd = new G4UIcmdWithABool("/process/eLoss/integral",this);
IntegCmd->SetGuidance("Switch true/false the integration of cross section over step.");
IntegCmd->SetParameterName("integ",true);
IntegCmd->SetDefaultValue(true);
IntegCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinSubSecCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minsubsec",this);
MinSubSecCmd->SetGuidance("Set the min. cut for subcutoff delta in range.");
MinSubSecCmd->SetParameterName("minsubsec",true);
MinSubSecCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MinEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/minKinEnergy",this);
MinEnCmd->SetGuidance("Set the min kinetic energy");
MinEnCmd->SetParameterName("emin",true);
MinEnCmd->SetUnitCategory("Energy");
MinEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
MaxEnCmd = new G4UIcmdWithADoubleAndUnit("/process/eLoss/maxKinEnergy",this);
MaxEnCmd->SetGuidance("Set the max kinetic energy");
MaxEnCmd->SetParameterName("emax",true);
MaxEnCmd->SetUnitCategory("Energy");
MaxEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
StepFuncCmd = new G4UIcommand("/process/eLoss/StepFunction",this);
StepFuncCmd->SetGuidance("Set the energy loss step limitation parameters.");
StepFuncCmd->SetGuidance(" dRoverR : max Range variation per step");
StepFuncCmd->SetGuidance(" finalRange: range for final step");
G4UIparameter* dRoverRPrm = new G4UIparameter("dRoverR",'d',false);
dRoverRPrm->SetGuidance("max Range variation per step (fractional number)");
dRoverRPrm->SetParameterRange("dRoverR>0. && dRoverR<=1.");
StepFuncCmd->SetParameter(dRoverRPrm);
G4UIparameter* finalRangePrm = new G4UIparameter("finalRange",'d',false);
finalRangePrm->SetGuidance("range for final step");
finalRangePrm->SetParameterRange("finalRange>0.");
StepFuncCmd->SetParameter(finalRangePrm);
G4UIparameter* unitPrm = new G4UIparameter("unit",'s',true);
unitPrm->SetGuidance("unit of finalRange");
unitPrm->SetDefaultValue("mm");
G4String unitCandidates = G4UIcommand::UnitsList(G4UIcommand::CategoryOf("mm"));
unitPrm->SetParameterCandidates(unitCandidates);
StepFuncCmd->SetParameter(unitPrm);
StepFuncCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EnergyLossMessengerSTD::~G4EnergyLossMessengerSTD()
{
delete RndmStepCmd;
delete EnlossFlucCmd;
delete SubSecCmd;
delete MinSubSecCmd;
delete MinEnCmd;
delete MaxEnCmd;
delete StepFuncCmd;
delete IntegCmd;
delete eLossDirectory;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EnergyLossMessengerSTD::SetNewValue(G4UIcommand* command,G4String newValue)
{
G4LossTableManager* lossTables = G4LossTableManager::Instance();
if (command == RndmStepCmd) {
lossTables->SetRandomStep(RndmStepCmd->GetNewBoolValue(newValue));
}
if (command == IntegCmd) {
lossTables->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
if (command == EnlossFlucCmd) {
lossTables->SetLossFluctuations(EnlossFlucCmd->GetNewBoolValue(newValue));
}
if (command == SubSecCmd) {
lossTables->SetSubCutoff(SubSecCmd->GetNewBoolValue(newValue));
}
if (command == MinEnCmd) {
lossTables->SetMinEnergy(MinEnCmd->GetNewDoubleValue(newValue));
}
if (command == MaxEnCmd) {
lossTables->SetMaxEnergy(MaxEnCmd->GetNewDoubleValue(newValue));
}
if (command == StepFuncCmd) {
G4double v1,v2;
char unts[30];
const char* t = newValue;
G4std::istrstream is((char*)t);
is >> v1 >> v2 >> unts;
G4String unt = unts;
v2 *= G4UIcommand::ValueOf(unt);
lossTables->SetStepLimits(v1,v2);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,10 +21,10 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossTables.cc,v 1.17 2001/10/29 09:40:52 maire Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EnergyLossTables.cc,v 1.27 2003/04/18 17:49:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
// modifications + "precise" functions added by L.Urban , 27/05/98
// modifications , TOF functions , 26/10/98, L.Urban
@@ -33,20 +33,32 @@
// 10.11.99: moved from RWT hash dictionary to STL map, G.Barrand, M.Maire
// 27.09.01 L.Urban , bug fixed (negative energy deposit)
// 26.10.01 all static functions moved from .icc files (mma)
// 15.01.03 Add interfaces required for "cut per region" (V.Ivanchenko)
// 12.03.03 Add warnings to obsolete interfaces (V.Ivanchenko)
// 10.04.03 Add call to G4LossTableManager is particle is not registered (V.Ivanchenko)
//
// -------------------------------------------------------------------
#include "G4EnergyLossTables.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4RegionStore.hh"
#include "G4LossTableManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EnergyLossTablesHelper G4EnergyLossTables::t ;
const G4ParticleDefinition* G4EnergyLossTables::lastParticle = 0;
G4EnergyLossTablesHelper G4EnergyLossTables::null_loss ;
const G4ParticleDefinition* G4EnergyLossTables::lastParticle = 0;
G4double G4EnergyLossTables::QQPositron = eplus*eplus ;
G4double G4EnergyLossTables::Chargesquare ;
G4int G4EnergyLossTables::oldIndex = -1 ;
G4double G4EnergyLossTables::rmin = 0. ;
G4double G4EnergyLossTables::rmax = 0. ;
G4double G4EnergyLossTables::Thigh = 0. ;
G4int G4EnergyLossTables::let_counter = 0;
G4int G4EnergyLossTables::let_max_num_warnings = 2;
G4bool G4EnergyLossTables::first_loss = true;
G4EnergyLossTables::helper_map G4EnergyLossTables::dict;
@@ -95,11 +107,15 @@ void G4EnergyLossTables::Register(
dict[p]= G4EnergyLossTablesHelper(tDEDX, tRange,tInverseRange,
tLabTime,tProperTime,lowestKineticEnergy,
highestKineticEnergy, massRatio,NumberOfBins);
t = GetTables(p) ; // important for cache !!!!!
lastParticle = p ;
Chargesquare = (p->GetPDGCharge())*(p->GetPDGCharge())/
QQPositron ;
if (first_loss ) {
null_loss = G4EnergyLossTablesHelper(0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0);
first_loss = false;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -109,7 +125,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetDEDXTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theDEDXTable;
return (*it).second.theDEDXTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -119,7 +135,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetRangeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theRangeTable;
return (*it).second.theRangeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -129,7 +145,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetInverseRangeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theInverseRangeTable;
return (*it).second.theInverseRangeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -139,7 +155,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetLabTimeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theLabTimeTable;
return (*it).second.theLabTimeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -149,7 +165,7 @@ const G4PhysicsTable* G4EnergyLossTables::GetProperTimeTable(
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) return 0;
return (*it).second.theProperTimeTable;
return (*it).second.theProperTimeTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -158,9 +174,11 @@ G4EnergyLossTablesHelper G4EnergyLossTables::GetTables(
const G4ParticleDefinition* p)
{
helper_map::iterator it;
if((it=dict.find(p))==dict.end()) {
G4Exception("G4EnergyLossTables::GetTables: table not found!");
exit(1);
if ((it=dict.find(p))==dict.end()) {
// G4cout << "Table is not found out for " << p->GetParticleName() << G4endl;
// G4Exception("G4EnergyLossTables::GetTables: table not found!");
// exit(1);
return null_loss;
}
return (*it).second;
}
@@ -172,6 +190,7 @@ G4double G4EnergyLossTables::GetDEDX(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -182,6 +201,7 @@ G4double G4EnergyLossTables::GetDEDX(
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -200,7 +220,7 @@ G4double G4EnergyLossTables::GetDEDX(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -216,6 +236,7 @@ G4double G4EnergyLossTables::GetLabTime(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -223,8 +244,9 @@ G4double G4EnergyLossTables::GetLabTime(
oldIndex = -1 ;
}
const G4PhysicsTable* labtimeTable= t.theLabTimeTable;
if (!labtimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double time;
@@ -243,7 +265,7 @@ G4double G4EnergyLossTables::GetLabTime(
t.theHighestKineticEnergy,isOut);
} else {
time = (*labtimeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -260,6 +282,7 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
G4double KineticEnergyEnd,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -267,9 +290,10 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
oldIndex = -1 ;
}
const G4PhysicsTable* labtimeTable= t.theLabTimeTable;
if (!labtimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
G4double timestart,timeend,deltatime,dTT;
G4bool isOut;
@@ -296,12 +320,12 @@ G4double G4EnergyLossTables::GetDeltaLabTime(
}
dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
if( dTT < dToverT )
scaledKineticEnergy = facT*KineticEnergyStart*t.theMassRatio;
else
scaledKineticEnergy = KineticEnergyEnd*t.theMassRatio;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
timeend = exp(ppar*log(scaledKineticEnergy/t.theLowestKineticEnergy))*
@@ -336,6 +360,7 @@ G4double G4EnergyLossTables::GetProperTime(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -343,6 +368,7 @@ G4double G4EnergyLossTables::GetProperTime(
oldIndex = -1 ;
}
const G4PhysicsTable* propertimeTable= t.theProperTimeTable;
if (!propertimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
G4int materialIndex = aMaterial->GetIndex();
@@ -380,6 +406,7 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
G4double KineticEnergyEnd,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -387,9 +414,10 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
oldIndex = -1 ;
}
const G4PhysicsTable* propertimeTable= t.theProperTimeTable;
if (!propertimeTable) ParticleHaveNoLoss(aParticle);
const G4double parlowen=0.4 , ppar=0.5-parlowen ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
const G4double dToverT = 0.05 , facT = 1. -dToverT ;
G4double timestart,timeend,deltatime,dTT;
G4bool isOut;
@@ -416,12 +444,12 @@ G4double G4EnergyLossTables::GetDeltaProperTime(
}
dTT = (KineticEnergyStart - KineticEnergyEnd)/KineticEnergyStart ;
if( dTT < dToverT )
scaledKineticEnergy = facT*KineticEnergyStart*t.theMassRatio;
else
scaledKineticEnergy = KineticEnergyEnd*t.theMassRatio;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
timeend = exp(ppar*log(scaledKineticEnergy/t.theLowestKineticEnergy))*
@@ -456,6 +484,7 @@ G4double G4EnergyLossTables::GetRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -467,6 +496,7 @@ G4double G4EnergyLossTables::GetRange(
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable || !rangeTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -488,7 +518,7 @@ G4double G4EnergyLossTables::GetRange(
t.theHighestKineticEnergy,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
@@ -505,6 +535,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
const G4Material *aMaterial)
// it returns the value of the kinetic energy for a given range
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -516,6 +547,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
const G4PhysicsTable* inverseRangeTable= t.theInverseRangeTable;
if (!dEdxTable || !inverseRangeTable) ParticleHaveNoLoss(aParticle);
G4double scaledrange,scaledKineticEnergy ;
G4bool isOut ;
@@ -566,7 +598,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -577,6 +609,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
@@ -595,7 +628,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
@@ -611,6 +644,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
G4double KineticEnergy,
const G4Material *aMaterial)
{
CPRWarning();
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
@@ -622,6 +656,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if (!dEdxTable || !rangeTable) ParticleHaveNoLoss(aParticle);
G4int materialIndex = aMaterial->GetIndex();
@@ -648,7 +683,7 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
Thighr,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
@@ -659,6 +694,299 @@ G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle ;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable )
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double dEdx;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx =(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut)
*sqrt(scaledKineticEnergy/t.theLowestKineticEnergy);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
}
return dEdx*Chargesquare;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetRange(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if(aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle ;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !rangeTable || !dEdxTable)
return G4LossTableManager::Instance()->GetRange(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double Range;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
Range = (*rangeTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut)+
(scaledKineticEnergy-t.theHighestKineticEnergy)/
(*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut);
}
return Range/(Chargesquare*t.theMassRatio);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseEnergyFromRange(
const G4ParticleDefinition *aParticle,
G4double range,
const G4MaterialCutsCouple *couple)
// it returns the value of the kinetic energy for a given range
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
const G4PhysicsTable* inverseRangeTable= t.theInverseRangeTable;
if ( !dEdxTable || !inverseRangeTable)
return G4LossTableManager::Instance()->GetEnergy(aParticle,range,couple);
G4double scaledrange,scaledKineticEnergy ;
G4bool isOut ;
G4int materialIndex = couple->GetIndex() ;
if(materialIndex != oldIndex)
{
oldIndex = materialIndex ;
rmin = (*inverseRangeTable)(materialIndex)->
GetLowEdgeEnergy(0) ;
rmax = (*inverseRangeTable)(materialIndex)->
GetLowEdgeEnergy(t.theNumberOfBins-2) ;
Thigh = (*inverseRangeTable)(materialIndex)->
GetValue(rmax,isOut) ;
}
scaledrange = range*Chargesquare*t.theMassRatio ;
if(scaledrange < rmin)
{
scaledKineticEnergy = t.theLowestKineticEnergy*
scaledrange*scaledrange/(rmin*rmin) ;
}
else
{
if(scaledrange < rmax)
{
scaledKineticEnergy = (*inverseRangeTable)(materialIndex)->
GetValue( scaledrange,isOut) ;
}
else
{
scaledKineticEnergy = Thigh +
(scaledrange-rmax)*
(*dEdxTable)(materialIndex)->
GetValue(Thigh,isOut) ;
}
}
return scaledKineticEnergy/t.theMassRatio ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseDEDX(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable )
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double dEdx;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
dEdx = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)
*(*dEdxTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>t.theHighestKineticEnergy) {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
t.theHighestKineticEnergy,isOut);
} else {
dEdx = (*dEdxTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
}
return dEdx*Chargesquare;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4EnergyLossTables::GetPreciseRangeFromEnergy(
const G4ParticleDefinition *aParticle,
G4double KineticEnergy,
const G4MaterialCutsCouple *couple)
{
if( aParticle != lastParticle)
{
t= GetTables(aParticle);
lastParticle = aParticle;
Chargesquare = (aParticle->GetPDGCharge())*
(aParticle->GetPDGCharge())/
QQPositron ;
oldIndex = -1 ;
}
const G4PhysicsTable* rangeTable= t.theRangeTable;
const G4PhysicsTable* dEdxTable= t.theDEDXTable;
if ( !dEdxTable || !rangeTable)
return G4LossTableManager::Instance()->GetDEDX(aParticle,KineticEnergy,couple);
G4int materialIndex = couple->GetIndex();
G4double Thighr = t.theHighestKineticEnergy*t.theLowestKineticEnergy/
(*rangeTable)(materialIndex)->
GetLowEdgeEnergy(1) ;
G4double scaledKineticEnergy = KineticEnergy*t.theMassRatio;
G4double Range;
G4bool isOut;
if (scaledKineticEnergy<t.theLowestKineticEnergy) {
Range = sqrt(scaledKineticEnergy/t.theLowestKineticEnergy)*
(*rangeTable)(materialIndex)->GetValue(
t.theLowestKineticEnergy,isOut);
} else if (scaledKineticEnergy>Thighr) {
Range = (*rangeTable)(materialIndex)->GetValue(
Thighr,isOut)+
(scaledKineticEnergy-Thighr)/
(*dEdxTable)(materialIndex)->GetValue(
Thighr,isOut);
} else {
Range = (*rangeTable)(materialIndex)->GetValue(
scaledKineticEnergy,isOut) ;
}
return Range/(Chargesquare*t.theMassRatio);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EnergyLossTables::CPRWarning()
{
// if (let_counter < let_max_num_warnings) {
// G4cout << G4endl;
// G4cout << "##### G4EnergyLossTable WARNING: The obsolete interface is used" << G4endl;
// G4cout << "##### Please, substitute G4Material by G4MaterialCutsCouple" << G4endl;
// G4cout << "##### Obsolete interface will be removed soon" << G4endl;
// G4cout << G4endl;
// let_counter++;
if ((G4RegionStore::GetInstance())->size() > 1) {
G4Exception("G4EnergyLossTables:: More than 1 region - table can't be accessed with obsolete interface");
exit(1);
}
// } else if (let_counter == let_max_num_warnings) {
// G4cout << "##### G4EnergyLossTable WARNING closed" << G4endl;
// let_counter++;
// }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EnergyLossTables::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle)
{
G4String s = "G4EnergyLossTables:: dE/dx table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,337 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4IonFluctuation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4IonFluctuations.hh"
#include "Randomize.hh"
#include "G4Poisson.hh"
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IonFluctuations::G4IonFluctuations(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minFraction(0.2)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4IonFluctuations::~G4IonFluctuations()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4IonFluctuations::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
if(dp->GetDefinition() != particle) {
particle = dp->GetDefinition();
particleMass = dp->GetMass();
charge = dp->GetCharge();
chargeSquare = charge*charge;
}
G4double siga = Dispersion(material,dp,tmax,length);
G4double loss = meanLoss;
// Gaussian fluctuation
if (meanLoss >= minNumberInteractionsBohr*tmax) {
// Increase fluctuations for big fractional energy loss
if ( meanLoss > minFraction*kineticEnergy ) {
G4double gam = (kineticEnergy - meanLoss)/particleMass + 1.0;
G4double b2 = 1.0 - 1.0/(gam*gam);
G4double x = b2/beta2;
G4double x3 = 1.0/(x*x*x);
siga *= 0.25*(1.0 + x)*(x3 + (1.0/b2 - 0.5)/(1.0/beta2 - 0.5) );
}
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0. || loss > 2.*meanLoss);
// Poisson fluctuations
} else {
G4double navr = meanLoss*meanLoss/siga;
G4double n = (G4double)G4Poisson(navr);
loss = meanLoss*n/navr;
}
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
G4double electronDensity = material->GetElectronDensity();
kineticEnergy = dp->GetKineticEnergy();
G4double gam = kineticEnergy/particleMass + 1.0;
beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
G4double zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
if ( beta2 < 3.0*theBohrBeta2*zeff ) {
G4double a = CoeffitientA (zeff);
G4double b = CoeffitientB (material, zeff);
siga *= (chargeSquare * a + b);
}
return siga;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientA(G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy * amu_c2/(particleMass*MeV) ;
static G4double a[96][4] = {
{-0.3291, -0.8312, 0.2460, -1.0220},
{-0.5615, -0.5898, 0.5205, -0.7258},
{-0.5280, -0.4981, 0.5519, -0.5865},
{-0.5125, -0.4625, 0.5660, -0.5190},
{-0.5127, -0.8595, 0.5626, -0.8721},
{-0.5174, -1.1930, 0.5565, -1.1980},
{-0.5179, -1.1850, 0.5560, -1.2070},
{-0.5209, -0.9355, 0.5590, -1.0250},
{-0.5255, -0.7766, 0.5720, -0.9412},
{-0.5776, -0.6665, 0.6598, -0.8484},
{-0.6013, -0.6045, 0.7321, -0.7671},
{-0.5781, -0.5518, 0.7605, -0.6919},
{-0.5587, -0.4981, 0.7835, -0.6195},
{-0.5466, -0.4656, 0.7978, -0.5771},
{-0.5406, -0.4690, 0.8031, -0.5718},
{-0.5391, -0.5061, 0.8024, -0.5974},
{-0.5380, -0.6483, 0.7962, -0.6970},
{-0.5355, -0.7722, 0.7962, -0.7839},
{-0.5329, -0.7720, 0.7988, -0.7846},
{-0.5335, -0.7671, 0.7984, -0.7933},
{-0.5324, -0.7612, 0.7998, -0.8031},
{-0.5305, -0.7300, 0.8031, -0.7990},
{-0.5307, -0.7178, 0.8049, -0.8216},
{-0.5248, -0.6621, 0.8165, -0.7919},
{-0.5180, -0.6502, 0.8266, -0.7986},
{-0.5084, -0.6408, 0.8396, -0.8048},
{-0.4967, -0.6331, 0.8549, -0.8093},
{-0.4861, -0.6508, 0.8712, -0.8432},
{-0.4700, -0.6186, 0.8961, -0.8132},
{-0.4545, -0.5720, 0.9227, -0.7710},
{-0.4404, -0.5226, 0.9481, -0.7254},
{-0.4288, -0.4778, 0.9701, -0.6850},
{-0.4199, -0.4425, 0.9874, -0.6539},
{-0.4131, -0.4188, 0.9998, -0.6332},
{-0.4089, -0.4057, 1.0070, -0.6218},
{-0.4039, -0.3913, 1.0150, -0.6107},
{-0.3987, -0.3698, 1.0240, -0.5938},
{-0.3977, -0.3608, 1.0260, -0.5852},
{-0.3972, -0.3600, 1.0260, -0.5842},
{-0.3985, -0.3803, 1.0200, -0.6013},
{-0.3985, -0.3979, 1.0150, -0.6168},
{-0.3968, -0.3990, 1.0160, -0.6195},
{-0.3971, -0.4432, 1.0050, -0.6591},
{-0.3944, -0.4665, 1.0010, -0.6825},
{-0.3924, -0.5109, 0.9921, -0.7235},
{-0.3882, -0.5158, 0.9947, -0.7343},
{-0.3838, -0.5125, 0.9999, -0.7370},
{-0.3786, -0.4976, 1.0090, -0.7310},
{-0.3741, -0.4738, 1.0200, -0.7155},
{-0.3969, -0.4496, 1.0320, -0.6982},
{-0.3663, -0.4297, 1.0430, -0.6828},
{-0.3630, -0.4120, 1.0530, -0.6689},
{-0.3597, -0.3964, 1.0620, -0.6564},
{-0.3555, -0.3809, 1.0720, -0.6454},
{-0.3525, -0.3607, 1.0820, -0.6289},
{-0.3505, -0.3465, 1.0900, -0.6171},
{-0.3397, -0.3570, 1.1020, -0.6384},
{-0.3314, -0.3552, 1.1130, -0.6441},
{-0.3235, -0.3531, 1.1230, -0.6498},
{-0.3150, -0.3483, 1.1360, -0.6539},
{-0.3060, -0.3441, 1.1490, -0.6593},
{-0.2968, -0.3396, 1.1630, -0.6649},
{-0.2935, -0.3225, 1.1760, -0.6527},
{-0.2797, -0.3262, 1.1940, -0.6722},
{-0.2704, -0.3202, 1.2100, -0.6770},
{-0.2815, -0.3227, 1.2480, -0.6775},
{-0.2880, -0.3245, 1.2810, -0.6801},
{-0.3034, -0.3263, 1.3270, -0.6778},
{-0.2936, -0.3215, 1.3430, -0.6835},
{-0.3282, -0.3200, 1.3980, -0.6650},
{-0.3260, -0.3070, 1.4090, -0.6552},
{-0.3511, -0.3074, 1.4470, -0.6442},
{-0.3501, -0.3064, 1.4500, -0.6442},
{-0.3490, -0.3027, 1.4550, -0.6418},
{-0.3487, -0.3048, 1.4570, -0.6447},
{-0.3478, -0.3074, 1.4600, -0.6483},
{-0.3501, -0.3283, 1.4540, -0.6669},
{-0.3494, -0.3373, 1.4550, -0.6765},
{-0.3485, -0.3373, 1.4570, -0.6774},
{-0.3462, -0.3300, 1.4630, -0.6728},
{-0.3462, -0.3225, 1.4690, -0.6662},
{-0.3453, -0.3094, 1.4790, -0.6553},
{-0.3844, -0.3134, 1.5240, -0.6412},
{-0.3848, -0.3018, 1.5310, -0.6303},
{-0.3862, -0.2955, 1.5360, -0.6237},
{-0.4262, -0.2991, 1.5860, -0.6115},
{-0.4278, -0.2910, 1.5900, -0.6029},
{-0.4303, -0.2817, 1.5940, -0.5927},
{-0.4315, -0.2719, 1.6010, -0.5829},
{-0.4359, -0.2914, 1.6050, -0.6010},
{-0.4365, -0.2982, 1.6080, -0.6080},
{-0.4253, -0.3037, 1.6120, -0.6150},
{-0.4335, -0.3245, 1.6160, -0.6377},
{-0.4307, -0.3292, 1.6210, -0.6447},
{-0.4284, -0.3204, 1.6290, -0.6380},
{-0.4227, -0.3217, 1.6360, -0.6438}
} ;
G4int iz = (G4int)zeff - 2 ;
if( 0 > iz ) iz = 0 ;
if(95 < iz ) iz = 95 ;
G4double q = 1.0 / (1.0 + a[iz][0]*pow(energy,a[iz][1])+
+ a[iz][2]*pow(energy,a[iz][3])) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4IonFluctuations::CoeffitientB(const G4Material* material, G4double& zeff)
{
// The aproximation of energy loss fluctuations
// Q.Yang et al., NIM B61(1991)149-155.
// Reduced energy in MeV/AMU
G4double energy = kineticEnergy *amu_c2/(particleMass*MeV) ;
G4int i = 0 ;
G4double factor = 1.0 ;
// The index of set of parameters i = 0 for protons(hadrons) in gases
// 1 for protons(hadrons) in solids
// 2 for ions in atomic gases
// 3 for ions in molecular gases
// 4 for ions in solids
static G4double b[5][4] = {
{0.1014, 0.3700, 0.9642, 3.987},
{0.1955, 0.6941, 2.522, 1.040},
{0.05058, 0.08975, 0.1419, 10.80},
{0.05009, 0.08660, 0.2751, 3.787},
{0.01273, 0.03458, 0.3951, 3.812}
} ;
// protons (hadrons)
if(1.5 > charge) {
if( kStateGas != material->GetState() ) i = 1 ;
// ions
} else {
factor = charge * pow(charge/zeff, 0.3333) ;
if( kStateGas == material->GetState() ) {
energy /= (charge * sqrt(charge)) ;
if(1 == (material->GetNumberOfElements())) {
i = 2 ;
} else {
i = 3 ;
}
} else {
energy /= (charge * sqrt(charge*zeff)) ;
i = 4 ;
}
}
G4double x = b[i][2] * (1.0 - exp( - energy * b[i][3] )) ;
G4double q = factor * x * b[i][0] /
((energy - b[i][1])*(energy - b[i][1]) + x*x) ;
return q ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,643 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4LewisModel
//
// Author: Laszlo Urban
//
// Creation date: 03.03.2001
//
// Modifications:
//
// 27-03-03 Move model part from G4MultipleScattering (V.Ivanchenko)
//
// Class Description:
//
// Implementation of Lewis model of multiple scattering
// H.W.Lewis Phys Rev 78 (1950) 526
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LewisModel.hh"
#include "Randomize.hh"
#include "G4Electron.hh"
#include "G4LossTableManager.hh"
#include "G4PhysicsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::G4LewisModel(G4double& m_dtrl, G4double& m_NuclCorrPar,
G4double& m_FactPar, G4double& m_facxsi,
G4bool& m_samplez, const G4String& nam)
: G4VEmModel(nam),
highKinEnergy(10.0*TeV),
lowKinEnergy(0.1*keV),
taubig(8.0),
tausmall(1.e-14),
taulim(1.e-5),
dtrl(m_dtrl),
NuclCorrPar (m_NuclCorrPar),
FactPar(m_FactPar),
facxsi(m_facxsi),
samplez(m_samplez),
stepmin(1.e-6*mm)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LewisModel::~G4LewisModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4LewisModel::IsInCharge(const G4ParticleDefinition* p)
{
return (p->GetPDGCharge() != 0.0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LewisModel::Initialise(const G4ParticleDefinition* p,
const G4DataVector&)
{
// set values of some data members
if((p->GetParticleName() == "e-") || (p->GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
sigmafactor = twopi*classic_electr_radius*classic_electr_radius;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::CrossSection(const G4Material* material,
const G4ParticleDefinition* p,
G4double kineticEnergy,
G4double,
G4double)
{
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int NumberOfElements = material->GetNumberOfElements();
// loop for element in the material
G4double sigma = 0.0;
for (G4int iel=0; iel<NumberOfElements; iel++)
{
G4double atomicNumber = (*theElementVector)[iel]->GetZ();
G4double atomicWeight = (*theElementVector)[iel]->GetA();
sigma += NbOfAtomsPerVolume[iel]*ComputeTransportCrossSection(p,
kineticEnergy,atomicNumber,atomicWeight);
}
sigma *= sigmafactor;
// Calculate lambda
if ( sigma > 0.0) sigma = 1.0/sigma;
else sigma = DBL_MAX;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::ComputeTransportCrossSection(
const G4ParticleDefinition* particle,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight)
{
const G4double epsfactor = 2.*electron_mass_c2*electron_mass_c2*
Bohr_radius*Bohr_radius/(hbarc*hbarc);
const G4double epsmin = 1.e-4 , epsmax = 1.e10;
const G4double Zdat[15] = { 4., 6.,13.,20.,26.,29.,32.,38.,47.,
50.,56.,64.,74.,79.,82. };
const G4double Tdat[23] = {0.0001*MeV,0.0002*MeV,0.0004*MeV,0.0007*MeV,
0.001*MeV,0.002*MeV,0.004*MeV,0.007*MeV,
0.01*MeV,0.02*MeV,0.04*MeV,0.07*MeV,
0.1*MeV,0.2*MeV,0.4*MeV,0.7*MeV,
1.*MeV,2.*MeV,4.*MeV,7.*MeV,10.*MeV,20.*MeV,
10000.0*MeV};
// corr. factors for e-/e+ lambda
G4double celectron[15][23] =
{{1.125,1.072,1.051,1.047,1.047,1.050,1.052,1.054,
1.054,1.057,1.062,1.069,1.075,1.090,1.105,1.111,
1.112,1.108,1.100,1.093,1.089,1.087,0.7235 },
{1.408,1.246,1.143,1.096,1.077,1.059,1.053,1.051,
1.052,1.053,1.058,1.065,1.072,1.087,1.101,1.108,
1.109,1.105,1.097,1.090,1.086,1.082,0.7925 },
{2.833,2.268,1.861,1.612,1.486,1.309,1.204,1.156,
1.136,1.114,1.106,1.106,1.109,1.119,1.129,1.132,
1.131,1.124,1.113,1.104,1.099,1.098,0.9147 },
{3.879,3.016,2.380,2.007,1.818,1.535,1.340,1.236,
1.190,1.133,1.107,1.099,1.098,1.103,1.110,1.113,
1.112,1.105,1.096,1.089,1.085,1.098,0.9700 },
{6.937,4.330,2.886,2.256,1.987,1.628,1.395,1.265,
1.203,1.122,1.080,1.065,1.061,1.063,1.070,1.073,
1.073,1.070,1.064,1.059,1.056,1.056,1.0022 },
{9.616,5.708,3.424,2.551,2.204,1.762,1.485,1.330,
1.256,1.155,1.099,1.077,1.070,1.068,1.072,1.074,
1.074,1.070,1.063,1.059,1.056,1.052,1.0158 },
{11.72,6.364,3.811,2.806,2.401,1.884,1.564,1.386,
1.300,1.180,1.112,1.082,1.073,1.066,1.068,1.069,
1.068,1.064,1.059,1.054,1.051,1.050,1.0284 },
{18.08,8.601,4.569,3.183,2.662,2.025,1.646,1.439,
1.339,1.195,1.108,1.068,1.053,1.040,1.039,1.039,
1.039,1.037,1.034,1.031,1.030,1.036,1.0515 },
{18.22,10.48,5.333,3.713,3.115,2.367,1.898,1.631,
1.498,1.301,1.171,1.105,1.077,1.048,1.036,1.033,
1.031,1.028,1.024,1.022,1.021,1.024,1.0834 },
{14.14,10.65,5.710,3.929,3.266,2.453,1.951,1.669,
1.528,1.319,1.178,1.106,1.075,1.040,1.027,1.022,
1.020,1.017,1.015,1.013,1.013,1.020,1.0937 },
{14.11,11.73,6.312,4.240,3.478,2.566,2.022,1.720,
1.569,1.342,1.186,1.102,1.065,1.022,1.003,0.997,
0.995,0.993,0.993,0.993,0.993,1.011,1.1140 },
{22.76,20.01,8.835,5.287,4.144,2.901,2.219,1.855,
1.677,1.410,1.224,1.121,1.073,1.014,0.986,0.976,
0.974,0.972,0.973,0.974,0.975,0.987,1.1410 },
{50.77,40.85,14.13,7.184,5.284,3.435,2.520,2.059,
1.837,1.512,1.283,1.153,1.091,1.010,0.969,0.954,
0.950,0.947,0.949,0.952,0.954,0.963,1.1750 },
{65.87,59.06,15.87,7.570,5.567,3.650,2.682,2.182,
1.939,1.579,1.325,1.178,1.108,1.014,0.965,0.947,
0.941,0.938,0.940,0.944,0.946,0.954,1.1922 },
// {45.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239, // paper.....
{55.60,47.34,15.92,7.810,5.755,3.767,2.760,2.239,
1.985,1.609,1.343,1.188,1.113,1.013,0.960,0.939,
0.933,0.930,0.933,0.936,0.939,0.949,1.2026 }};
G4double cpositron[15][23] = {
{2.589,2.044,1.658,1.446,1.347,1.217,1.144,1.110,
1.097,1.083,1.080,1.086,1.092,1.108,1.123,1.131,
1.131,1.126,1.117,1.108,1.103,1.100,0.7235 },
{3.904,2.794,2.079,1.710,1.543,1.325,1.202,1.145,
1.122,1.096,1.089,1.092,1.098,1.114,1.130,1.137,
1.138,1.132,1.122,1.113,1.108,1.102,0.7925 },
{7.970,6.080,4.442,3.398,2.872,2.127,1.672,1.451,
1.357,1.246,1.194,1.179,1.178,1.188,1.201,1.205,
1.203,1.190,1.173,1.159,1.151,1.145,0.9147 },
{9.714,7.607,5.747,4.493,3.815,2.777,2.079,1.715,
1.553,1.353,1.253,1.219,1.211,1.214,1.225,1.228,
1.225,1.210,1.191,1.175,1.166,1.174,0.9700 },
{17.97,12.95,8.628,6.065,4.849,3.222,2.275,1.820,
1.624,1.382,1.259,1.214,1.202,1.202,1.214,1.219,
1.217,1.203,1.184,1.169,1.160,1.151,1.0022 },
{24.83,17.06,10.84,7.355,5.767,3.707,2.546,1.996,
1.759,1.465,1.311,1.252,1.234,1.228,1.238,1.241,
1.237,1.222,1.201,1.184,1.174,1.159,1.0158 },
{23.26,17.15,11.52,8.049,6.375,4.114,2.792,2.155,
1.880,1.535,1.353,1.281,1.258,1.247,1.254,1.256,
1.252,1.234,1.212,1.194,1.183,1.170,1.0284 },
{22.33,18.01,12.86,9.212,7.336,4.702,3.117,2.348,
2.015,1.602,1.385,1.297,1.268,1.251,1.256,1.258,
1.254,1.237,1.214,1.195,1.185,1.179,1.0515 },
{33.91,24.13,15.71,10.80,8.507,5.467,3.692,2.808,
2.407,1.873,1.564,1.425,1.374,1.330,1.324,1.320,
1.312,1.288,1.258,1.235,1.221,1.205,1.0834 },
{32.14,24.11,16.30,11.40,9.015,5.782,3.868,2.917,
2.490,1.925,1.596,1.447,1.391,1.342,1.332,1.327,
1.320,1.294,1.264,1.240,1.226,1.214,1.0937 },
{29.51,24.07,17.19,12.28,9.766,6.238,4.112,3.066,
2.602,1.995,1.641,1.477,1.414,1.356,1.342,1.336,
1.328,1.302,1.270,1.245,1.231,1.233,1.1140 },
{38.19,30.85,21.76,15.35,12.07,7.521,4.812,3.498,
2.926,2.188,1.763,1.563,1.484,1.405,1.382,1.371,
1.361,1.330,1.294,1.267,1.251,1.239,1.1410 },
{49.71,39.80,27.96,19.63,15.36,9.407,5.863,4.155,
3.417,2.478,1.944,1.692,1.589,1.480,1.441,1.423,
1.409,1.372,1.330,1.298,1.280,1.258,1.1750 },
{59.25,45.08,30.36,20.83,16.15,9.834,6.166,4.407,
3.641,2.648,2.064,1.779,1.661,1.531,1.482,1.459,
1.442,1.400,1.354,1.319,1.299,1.272,1.1922 },
{56.38,44.29,30.50,21.18,16.51,10.11,6.354,4.542,
3.752,2.724,2.116,1.817,1.692,1.554,1.499,1.474,
1.456,1.412,1.364,1.328,1.307,1.282,1.2026 }};
G4double sigma;
G4double Z23 = 2.*log(AtomicNumber)/3.; Z23 = exp(Z23);
G4double ParticleMass = particle->GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/ParticleMass ;
G4double c = ParticleMass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
G4double w = c-2. ;
G4double tau = 0.5*(w+sqrt(w*w+4.*c)) ;
KineticEnergy = electron_mass_c2*tau ;
}
G4double Charge = particle->GetPDGCharge();
G4double ChargeSquare = Charge*Charge/(eplus*eplus);
G4double TotalEnergy = KineticEnergy + electron_mass_c2 ;
G4double beta2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(TotalEnergy*TotalEnergy);
G4double bg2 = KineticEnergy*(TotalEnergy+electron_mass_c2)
/(electron_mass_c2*electron_mass_c2);
G4double eps = epsfactor*bg2/Z23;
if (eps<epsmin) sigma = 2.*eps*eps;
else if(eps<epsmax) sigma = log(1.+2.*eps)-2.*eps/(1.+2.*eps);
else sigma = log(2.*eps)-1.+1./eps;
sigma *= ChargeSquare*AtomicNumber*AtomicNumber/(beta2*bg2);
// nuclear size effect correction for high energy
// ( a simple approximation at present)
G4double corrnuclsize,a,w1,w2,w;
G4double x0 = 1. - NuclCorrPar*ParticleMass/(KineticEnergy*
exp(log(AtomicWeight/(g/mole))/3.));
if ( x0 < -1. || KineticEnergy <= 10.*MeV)
{
x0 = -1.;
corrnuclsize = 1.;
}
else
{
a = 1.+1./eps;
if (eps > epsmax) w1=log(2.*eps)+1./eps-3./(8.*eps*eps);
else w1=log((a+1.)/(a-1.))-2./(a+1.);
w = 1./((1.-x0)*eps);
if (w < epsmin) w2=-log(w)-1.+2.*w-1.5*w*w;
else w2 = log((a-x0)/(a-1.))-(1.-x0)/(a-x0);
corrnuclsize = w1/w2;
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
while ((iZ>=0)&&(Zdat[iZ]>=AtomicNumber)) iZ -= 1;
if (iZ==14) iZ = 13;
if (iZ==-1) iZ = 0 ;
G4double Z1 = Zdat[iZ];
G4double Z2 = Zdat[iZ+1];
G4double ratZ = (AtomicNumber-Z1)/(Z2-Z1);
// get bin number in T (beta2)
G4int iT = 22;
while ((iT>=0)&&(Tdat[iT]>=KineticEnergy)) iT -= 1;
if(iT==22) iT = 21;
if(iT==-1) iT = 0 ;
// calculate betasquare values
G4double T = Tdat[iT], E = T + electron_mass_c2;
G4double b2small = T*(E+electron_mass_c2)/(E*E);
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = celectron[iZ][iT+1];
c2 = celectron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
if (Charge > 0.)
{
c1 = cpositron[iZ][iT];
c2 = cpositron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
c1 = cpositron[iZ][iT+1];
c2 = cpositron[iZ+1][iT+1];
cc2 = c1+ratZ*(c2-c1);
corr = cc1+ratb2*(cc2-cc1);
sigma /= corr;
}
// nucl. size correction for particles other than e+/e- only at present !!!!
if((particle->GetParticleName() != "e-") &&
(particle->GetParticleName() != "e+") )
sigma /= corrnuclsize;
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::GeomPathLength(
G4PhysicsTable* theLambdaTable,
const G4MaterialCutsCouple* couple,
const G4ParticleDefinition* particle,
G4double& T0,
G4double lambda,
G4double range,
G4double truePathLength)
{
// do the true -> geom transformation
const G4double ztmin = 1./3., ztmax = 0.98 ;
lambda0 = lambda;
lambda1 = -1.;
lambdam = -1.;
alam = range;
zm = 1.;
cthm = 1.;
tPathLength = truePathLength;
G4double tau = tPathLength/lambda0 ;
if (tau <= tausmall) return tPathLength;
G4double zmean = tPathLength;
if (tPathLength < range*dtrl) {
zmean = lambda0*(1.-exp(-tau));
} else {
G4LossTableManager* theManager = G4LossTableManager::Instance();
G4double T1 = theManager->GetEnergy(particle,range-tPathLength,couple);
if (theLambdaTable) {
G4bool b;
lambda1 = ((*theLambdaTable)[couple->GetIndex()])->GetValue(T1,b);
} else {
lambda1 = CrossSection(couple->GetMaterial(),particle,T1,0.0,1.0);
}
if (T0 > particle->GetPDGMass()) alam = lambda0*tPathLength/(lambda0-lambda1) ;
G4double blam = 1.+alam/lambda0 ;
if (tPathLength < 2.*dtrl*range) {
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
} else {
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
G4double clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
G4double zPathLength = zmean ;
G4double zt = zmean/tPathLength ;
if (tPathLength >= stepmin && samplez && zt > ztmin && zt < ztmax) {
G4double cz = 0.5*(3.*zt-1.)/(1.-zt) ;
G4double cz1 = 1.+cz ;
G4double u0 = cz/cz1 ;
G4double u,grej ;
G4double grej0 = exp(cz*log(u0))*(1.-u0) ;
do {
u = exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(u))*(1.-u) ;
if (grej > grej0)
G4cout << "G4LewisModel: Warning! majorant "
<< grej0 << " < " << grej << G4endl;
} while (grej < grej0*G4UniformRand()) ;
zPathLength = tPathLength*u ;
}
return zPathLength ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::TrueStepLength(G4double geomStepLength)
{
G4double trueLength = geomStepLength;
if (geomStepLength > lambda0*tausmall) {
G4double blam = 1.+alam/lambda0;
// G4cout << "alam= " << alam << " blam= " << blam << " lambda1= " << lambda1 << G4endl;
if (lambda1 < 0.) {
trueLength = -lambda0*log(1.-geomStepLength/lambda0) ;
} else if (lambdam < 0.) {
if (blam*geomStepLength < alam)
trueLength = alam*(1.-exp(log(1.-blam*geomStepLength/alam)/blam));
else
trueLength = tPathLength;
} else {
if (geomStepLength <= zm) {
// ??? here is a problems - redefine variable
lambdam = -1.;
if(blam*geomStepLength < alam )
trueLength = alam*(1.-exp(log(1.-blam*geomStepLength/alam)/blam));
else
trueLength = 0.5*tPathLength;
} else {
G4double clam = 1.+alam/lambdam;
// G4cout << "clam= " << clam << " zm= " << zm << " cthm= " << cthm << G4endl;
if(clam*(geomStepLength-zm)/(alam*cthm) < 1.)
trueLength = 0.5*tPathLength + alam*(1.-
exp(log(1.-clam*(geomStepLength-zm)/(alam*cthm)))/clam) ;
else
trueLength = tPathLength;
}
}
// G4cout << "tLenth= " << trueLength << " tpl= " << tPathLength << G4endl;
if(trueLength > tPathLength) trueLength = tPathLength;
if(trueLength < geomStepLength) trueLength = geomStepLength;
}
return trueLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleCosineTheta(G4double trueStepLength)
{
G4double cth = 1.;
currentTau = trueStepLength/lambda0;
if(trueStepLength < stepmin)
cth = exp(-currentTau) ;
else
{
// G4cout << "tau= " << currentTau << " lambda1= " << lambda1 << " lambdam= " << lambdam << G4endl;
if (currentTau > taubig) cth = -1.+2.*G4UniformRand();
else if (currentTau >= tausmall)
{
if(lambda1 > 0.)
{
if (lambdam < 0.)
currentTau = -alam*log(1.-trueStepLength/alam)/lambda0 ;
else
currentTau = -log(cthm)-alam*
log(1.-(trueStepLength-0.5*tPathLength)/alam)/lambdam ;
}
if(currentTau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax = 25. ;
const G4double tau0 = 0.02 ;
G4double a;
G4double w = log(currentTau/tau0) ;
if (currentTau < tau0) a = (alfa1-alfa2*w)/currentTau ;
else a = (alfa1+alfa3*w)/currentTau ;
G4double x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
G4double c = a*(b-x0) ;
if(a*currentTau < c0) c = c0*(b-x0)/currentTau ;
if(c == 1.) c=1.000001 ;
if(c == 2.) c=2.000001 ;
if(c == 3.) c=3.000001 ;
G4double ea = 0.0;
if (a*(1.-x0) < amax) ea = exp(-a*(1.-x0)) ;
G4double eaa = 1.-ea ;
G4double xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
G4double b1 = b+1. ;
G4double bx = b-x0 ;
G4double eb1= exp((c-1.)*log(b1)) ;
G4double ebx= exp((c-1.)*log(bx)) ;
G4double xmean2 = (x0*eb1+ebx+(eb1*bx-b1*ebx)/(2.-c))/(eb1-ebx) ;
G4double xmeanth = exp(-currentTau) ;
G4double cnorm1 = a/eaa ;
G4double cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
G4double f1x0 = cnorm1*exp(-a*(1.-x0)) ;
G4double f2x0 = cnorm2/exp(c*log(b-x0)) ;
// from continuity at x=x0
G4double prob = f2x0/(f1x0+f2x0) ;
// from xmean = xmeanth
G4double qprob = (f1x0+f2x0)*xmeanth/(f2x0*xmean1+f1x0*xmean2) ;
// protection against qprob > 1
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
/*
G4cout << "tau= " << currentTau << " prob= " << prob << " qprob= " << qprob << G4endl;
G4cout << "ea= " << ea << " eaa= " << eaa << " a= " << a
<< " b= " << b << " b1= " << b1 << " bx= " << bx
<< " ebx= " << ebx << " eb1= " << eb1 << " c= " << c
<< G4endl;
*/
// sampling of costheta
if (G4UniformRand() < qprob)
{
if (G4UniformRand() < prob)
cth = 1.+log(ea+G4UniformRand()*eaa)/a ;
else
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
{
cth = -1.+2.*G4UniformRand();
}
}
}
}
// G4cout << "cth= " << cth << G4endl;
return cth;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LewisModel::SampleDisplacement()
{
const G4double kappa = 2.5;
const G4double kappapl1 = kappa+1.;
const G4double kappami1 = kappa-1.;
G4double rmean = 0.0;
if (currentTau >= tausmall) {
if (currentTau < taulim) {
rmean = kappa*currentTau*currentTau*currentTau*(1.-kappapl1*currentTau*0.25)/6. ;
} else {
G4double etau = 0.0;
if (currentTau<taubig) etau = exp(-currentTau);
rmean = -kappa*currentTau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += currentTau-kappapl1/kappa+kappa*etau/kappami1;
// G4cout << "tau= " << currentTau << " lambda0= " << lambda0 << " etau= " << etau << " kappa= " << kappa << G4endl;
}
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
// G4cout << "rmean= " << rmean << G4endl;
}
return rmean;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -29,10 +29,12 @@
// File name: G4LossTableBuilder
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// 23.01.2003 V.Ivanchenko Cut per region
//
// Class Description:
//
@@ -59,16 +61,16 @@ G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
if(!n_vectors) return 0;
G4PhysicsVector* pv = (*(list[0]))[0];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsTable* theTable = new G4PhysicsTable();
G4bool b;
for (size_t i=0; i<n_vectors; i++) {
G4PhysicsVector* pv = (*(list[0]))[i];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
for (size_t j=0; j<nbins; j++) {
@@ -80,15 +82,15 @@ G4PhysicsTable* G4LossTableBuilder::BuildDEDXTable(
dedx += ((*(list[k]))[i])->GetValue(energy, b);
}
v->PutValue(j, dedx);
v->PutValue(j, dedx);
}
theTable->insert(v);
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
const G4PhysicsTable* dedxTable)
// Build range table from the energy loss table
@@ -99,17 +101,16 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
G4bool b;
size_t n = 100;
G4double del = 1.0/(G4double)n;
G4PhysicsVector* pv = (*dedxTable)[0];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsTable* theTable = new G4PhysicsTable();
for (size_t i=0; i<n_vectors; i++) {
G4PhysicsVector* pv = (*dedxTable)[i];
size_t nbins = pv->GetVectorLength();
G4double elow = pv->GetLowEdgeEnergy(0);
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
pv = (*dedxTable)[i];
G4double dedx1 = pv->GetValue(elow, b);
G4double range = 0.5*elow/dedx1;
v->PutValue(0,range);
@@ -135,11 +136,11 @@ G4PhysicsTable* G4LossTableBuilder::BuildRangeTable(
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
const G4PhysicsTable* dedxTable,
const G4PhysicsTable* rangeTable)
@@ -178,11 +179,11 @@ G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
energy2 = pv->GetLowEdgeEnergy(ihigh);
range2 = pv->GetValue(energy2, b);
range2 = pv->GetValue(energy2, b);
if(range2 >= range || ihigh == nbins-1) {
ilow = ihigh - 1;
energy1 = pv->GetLowEdgeEnergy(ilow);
range1 = pv->GetValue(energy1, b);
range1 = pv->GetValue(energy1, b);
break;
}
}
@@ -194,7 +195,7 @@ G4PhysicsTable* G4LossTableBuilder::BuildInverseRangeTable(
theTable->insert(v);
}
return theTable;
}
return theTable;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -28,13 +28,21 @@
//
// File name: G4LossTableManager
//
// Author: Vladimir Ivanchenko
//
// Author: Vladimir Ivanchenko
//
// Creation date: 03.01.2002
//
// Modifications:
// Modifications:
//
// Class Description:
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 15-02-03 Lambda table can be scaled (V.Ivanchenko)
// 17-02-03 Fix problem of store/restore tables (V.Ivanchenko)
// 10-03-03 Add Ion registration (V.Ivanchenko)
// 25-03-03 Add deregistration (V.Ivanchenko)
// 02-04-03 Change messenger (V.Ivanchenko)
// 26-04-03 Fix retrieve tables (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
//
@@ -42,12 +50,13 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LossTableManager.hh"
#include "G4EnergyLossMessengerSTD.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4PhysicsTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProcessManager.hh"
#include "G4Electron.hh"
#include "G4VMultipleScattering.hh"
G4LossTableManager* G4LossTableManager::theInstance = 0;
@@ -65,6 +74,13 @@ G4LossTableManager* G4LossTableManager::Instance()
G4LossTableManager::~G4LossTableManager()
{
for (G4int i=0; i<n_loss; i++) {
if( loss_vector[i] ) delete loss_vector[i];
}
size_t msc = msc_vector.size();
for (size_t j=0; j<msc; j++) {
if(msc_vector[j] ) delete msc_vector[j];
} Clear();
delete theMessenger;
delete tableBuilder;
}
@@ -72,10 +88,11 @@ G4LossTableManager::~G4LossTableManager()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4LossTableManager::G4LossTableManager()
{
{
n_loss = 0;
first_entry = true;
all_tables_are_built = false;
all_particles_are_mapped = false;
all_tables_are_stored = false;
electron_table_are_built = false;
currentLoss = 0;
currentParticle = 0;
@@ -88,7 +105,7 @@ G4LossTableManager::G4LossTableManager()
eIonisation = 0;
minKinEnergy = 0.1*eV;
maxKinEnergy = 100.0*GeV;
theMessenger = new G4EnergyLossMessengerSTD();
theMessenger = new G4EnergyLossMessenger();
theElectron = G4Electron::Electron();
tableBuilder = new G4LossTableBuilder();
integral = true;
@@ -98,22 +115,14 @@ G4LossTableManager::G4LossTableManager()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Clear()
{
{
all_tables_are_built = false;
all_particles_are_mapped = false;
electron_table_are_built = false;
eIonisation = 0;
currentLoss = 0;
currentParticle = 0;
if(n_loss)
if(n_loss)
{
for(G4int i=0; i<n_loss; i++)
{
if(dedx_vector[i]) dedx_vector[i]->clearAndDestroy();
if(range_vector[i]) range_vector[i]->clearAndDestroy();
if(inv_range_vector[i]) inv_range_vector[i]->clearAndDestroy();
}
dedx_vector.clear();
range_vector.clear();
inv_range_vector.clear();
@@ -138,44 +147,95 @@ void G4LossTableManager::Register(G4VEnergyLossSTD* p)
range_vector.push_back(0);
inv_range_vector.push_back(0);
tables_are_built.push_back(false);
all_particles_are_mapped = false;
all_tables_are_built = false;
/*
p->SetLossFluctuations(lossFluctuationFlag);
p->SetSubCutoff(subCutoffFlag);
p->SetRandomStep(rndmStepFlag);
p->SetMinSubRange(minSubRange);
p->SetMinKinEnergy(minKinEnergy);
p->SetMaxKinEnergy(maxKinEnergy);
p->SetStepLimits(maxRangeVariation, maxFinalStep);
p->SetIntegral(integral);
*/
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::DeRegister(G4VEnergyLossSTD* p)
{
for (G4int i=0; i<n_loss; i++) {
if(loss_vector[i] == p) loss_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Register(G4VMultipleScattering* p)
{
msc_vector.push_back(p);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::DeRegister(G4VMultipleScattering* p)
{
size_t msc = msc_vector.size();
for (size_t i=0; i<msc; i++) {
if(msc_vector[i] == p) msc_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::RegisterIon(const G4ParticleDefinition* ion, G4VEnergyLossSTD* p)
{
loss_map[ion] = p;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4EnergyLossMessenger* G4LossTableManager::GetMessenger()
{
return theMessenger;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle)
{
G4String s = "G4LossTableManager:: dE/dx table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::Initialise()
void G4LossTableManager::Initialise(const G4ParticleDefinition* aParticle)
{
all_tables_are_built = true;
if (first_entry) {
first_entry = false;
firstParticle = aParticle;
}
for(G4int j=0; j<n_loss; j++) {
const G4ParticleDefinition* pd = loss_vector[j]->Particle();
if (!pd) {
pd = loss_vector[j]->GetProcessManager()->GetParticleType();
loss_vector[j]->SetParticle(pd);
}
if(!tables_are_built[j]) all_tables_are_built = false;
if(pd != part_vector[j]) {
part_vector[j] = pd;
base_part_vector[j] = loss_vector[j]->BaseParticle();
}
if(1 < verbose) {
G4String nm = "unknown";
const G4ParticleDefinition* pd = loss_vector[j]->Particle();
if(pd) nm = pd->GetParticleName();
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << nm
<< " tables_are_built= " << tables_are_built[j]
<< " procFlag= " << loss_vector[j]->TablesAreBuilt()
<< " all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
if(!loss_vector[j]->TablesAreBuilt()) {
all_tables_are_built = false;
break;
}
}
// All tables have to be rebuilt
if(all_particles_are_mapped && all_tables_are_built) {
for(G4int i=0; i<n_loss; i++) {
if (all_tables_are_built && firstParticle == aParticle) {
for (G4int i=0; i<n_loss; i++) {
tables_are_built[i] = false;
}
all_tables_are_built = false;
@@ -183,29 +243,9 @@ void G4LossTableManager::Initialise()
loss_map.clear();
}
// map all particles
if(!all_particles_are_mapped) {
const G4ParticleDefinition* pd;
for(G4int i=0; i<n_loss; i++) {
if(!part_vector[i]) {
pd = loss_vector[i]->Particle();
if(!pd) {
pd = loss_vector[i]->GetProcessManager()->GetParticleType();
loss_vector[i]->SetParticle(pd);
}
if(pd == theElectron) eIonisation = loss_vector[i];
part_vector[i] = pd;
pd = loss_vector[i]->BaseParticle();
base_part_vector[i] = pd;
}
}
all_particles_are_mapped = true;
}
if(1 < verbose) {
G4cout << "electron_table_are_built= " << electron_table_are_built
<< " all_tables_are_built= " << all_tables_are_built
<< " all_particles_are_mapped= " << all_particles_are_mapped
<< " all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
@@ -213,79 +253,77 @@ void G4LossTableManager::Initialise()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::BuildDEDXTable(const G4ParticleDefinition* aParticle)
void G4LossTableManager::BuildPhysicsTable(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable() for "
<< aParticle->GetParticleName()
if(0 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable() for "
<< aParticle->GetParticleName()
<< G4endl;
}
Initialise();
Initialise(aParticle);
// identify all particles and built electron table
if(!electron_table_are_built) {
eIonisation = BuildTables(theElectron);
currentLoss = eIonisation;
currentParticle = theElectron;
electron_table_are_built = true;
}
// If particle is not an electron
// If particle is not an electron
if(aParticle != theElectron) {
for(G4int i=0; i<n_loss; i++) {
if(1 < verbose) {
G4String nm = "0";
G4String nm1= "0";
G4String nm2= "0";
const G4ParticleDefinition* pd = loss_vector[i]->Particle();
const G4ParticleDefinition* bpd = loss_vector[i]->BaseParticle();
if(pd) nm = pd->GetParticleName();
if(bpd) nm2 = bpd->GetParticleName();
if(part_vector[i]) nm1 = part_vector[i]->GetParticleName();
G4cout << "For " << loss_vector[i]->GetProcessName()
<< " for " << nm
<< " (" << nm1 << ") "
<< " base_part= " << nm2
<< " tables_are_built= " << tables_are_built[i]
<< G4endl;
}
if(aParticle == part_vector[i]) {
if(tables_are_built[i]) break;
base_part_vector[i] = loss_vector[i]->BaseParticle();
if(!base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = BuildTables(aParticle);
for(G4int j=0; j<i; j++) {
if(aParticle == base_part_vector[j]) {
if (aParticle == base_part_vector[j]) {
tables_are_built[j] = true;
G4VEnergyLossSTD* em = loss_vector[j];
G4VEnergyLossSTD* em = loss_vector[j];
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[j]] = hIonisation;
if(em->SecondaryParticle() == theElectron) {
em->SetLambdaTable(hIonisation->LambdaTable());
em->SetSubLambdaTable(hIonisation->SubLambdaTable());
loss_map[part_vector[j]] = em;
if (em->SecondaryParticle() == theElectron) {
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
if (0 < verbose) {
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << part_vector[j]->GetParticleName()
<< " base_part= " << base_part_vector[j]->GetParticleName()
<< " tables_are_built= " << G4endl;
}
}
}
} else {
G4VEnergyLossSTD* em = loss_vector[i];
for(G4int j=0; j<n_loss; j++) {
if(part_vector[j] == base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
if(tables_are_built[j] && hIonisation->DEDXTable()) {
tables_are_built[i] = true;
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[i]] = hIonisation;
if(em->SecondaryParticle() == theElectron) {
if (tables_are_built[j] && part_vector[j] == base_part_vector[i]) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
tables_are_built[i] = true;
em->Initialise();
em->SetDEDXTable(hIonisation->DEDXTable());
em->SetRangeTable(hIonisation->RangeTable());
em->SetInverseRangeTable(hIonisation->InverseRangeTable());
em->SetLambdaTable(hIonisation->LambdaTable());
em->SetSubLambdaTable(hIonisation->SubLambdaTable());
loss_map[part_vector[i]] = em;
if (em->SecondaryParticle() == theElectron)
em->SetSecondaryRangeTable(eIonisation->RangeTable());
}
break;
if (0 < verbose) {
G4cout << "For " << em->GetProcessName()
<< " for " << part_vector[i]->GetParticleName()
<< " base_part= " << base_part_vector[i]->GetParticleName()
<< " tables_are_built= " << G4endl;
}
break;
}
}
}
@@ -293,60 +331,105 @@ void G4LossTableManager::BuildDEDXTable(const G4ParticleDefinition* aParticle)
}
}
}
all_tables_are_built = true;
for (G4int ii=0; ii<n_loss; ii++) {
if ( !tables_are_built[ii] ) {
all_tables_are_built = false;
break;
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildDEDXTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
G4cout << "G4LossTableManager::BuildDEDXTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::RetrieveDEDXTable(const G4ParticleDefinition* aParticle,
G4VEnergyLossSTD* theModel)
void G4LossTableManager::RetrievePhysicsTables(const G4ParticleDefinition* aParticle,
G4VEnergyLossSTD* theLoss)
{
for(G4int i=0; i<n_loss; i++) {
if(theModel == loss_vector[i]) {
if(0 < verbose) {
G4cout << "G4LossTableManager::RetrievePhysicsTable() for "
<< aParticle->GetParticleName()
<< G4endl;
}
if (first_entry) Initialise(aParticle);
if (all_tables_are_built) return;
G4bool hasRange = false;
for (G4int i=0; i<n_loss; i++) {
if ( theLoss == loss_vector[i] ) {
tables_are_built[i] = true;
if(theModel->DEDXTable()) {
for(G4int j=0; j<n_loss; j++) {
if(j != i && tables_are_built[j]) {
if(aParticle == base_part_vector[j]) {
G4VEnergyLossSTD* em = loss_vector[j];
em->SetDEDXTable(theModel->DEDXTable());
em->SetRangeTable(theModel->RangeTable());
em->SetInverseRangeTable(theModel->InverseRangeTable());
loss_map[part_vector[j]] = theModel;
}
}
}
} else {
const G4ParticleDefinition* bp = theModel->BaseParticle();
for(G4int j=0; j<n_loss; j++) {
if(j != i && tables_are_built[j]) {
if(bp == part_vector[j] && loss_vector[j]->DEDXTable()) {
G4VEnergyLossSTD* hIonisation = loss_vector[j];
theModel->SetDEDXTable(hIonisation->DEDXTable());
theModel->SetRangeTable(hIonisation->RangeTable());
theModel->SetInverseRangeTable(hIonisation->InverseRangeTable());
loss_map[part_vector[j]] = hIonisation;
break;
}
}
}
if (theLoss->RangeTable()) {
if (part_vector[i] == theElectron) {
eIonisation = theLoss;
currentLoss = theLoss;
currentParticle = theElectron;
electron_table_are_built = true;
}
loss_map[part_vector[i]] = theLoss;
hasRange = true;
if (0 < verbose) {
G4cout << "dEdx and Range tables are defined for "
<< aParticle->GetParticleName()
<< G4endl;
}
}
}
if (electron_table_are_built && theLoss->SecondaryParticle() == theElectron)
theLoss->SetSecondaryRangeTable(eIonisation->RangeTable());
}
if ( hasRange ) {
for (G4int j=0; j<n_loss; j++) {
if ( base_part_vector[j] == aParticle && !tables_are_built[j] ) {
G4VEnergyLossSTD* em = loss_vector[j];
tables_are_built[j] = true;
em->Initialise();
em->SetDEDXTable(theLoss->DEDXTable());
em->SetRangeTable(theLoss->RangeTable());
em->SetInverseRangeTable(theLoss->InverseRangeTable());
em->SetLambdaTable(theLoss->LambdaTable());
em->SetSubLambdaTable(theLoss->SubLambdaTable());
if (electron_table_are_built && em->SecondaryParticle() == theElectron)
em->SetSecondaryRangeTable(eIonisation->RangeTable());
loss_map[part_vector[j]] = em;
if (1 < verbose) {
G4String nm = "0";
G4String nm1= "0";
G4String nm2= "0";
const G4ParticleDefinition* pd = part_vector[j];
const G4ParticleDefinition* bpd = base_part_vector[j];
if (pd) nm = pd->GetParticleName();
if (bpd) nm2 = bpd->GetParticleName();
if (part_vector[j]) nm1 = part_vector[j]->GetParticleName();
G4cout << "For " << loss_vector[j]->GetProcessName()
<< " for " << nm
<< " (" << nm1 << ") "
<< " base_part= " << nm2
<< " tables_are_built= " << tables_are_built[j]
<< G4endl;
}
}
}
}
all_tables_are_built = true;
for (G4int ii=0; ii<n_loss; ii++) {
if ( !tables_are_built[ii] ) {
all_tables_are_built = false;
break;
}
}
// identify all particles and built electron table
if(aParticle == theElectron) {
electron_table_are_built = true;
for(G4int i=0; i<n_loss; i++) {
if(loss_vector[i]->SecondaryParticle() == theElectron) {
loss_vector[i]->SetSecondaryRangeTable(theModel->RangeTable());
}
}
if(0 < verbose) {
G4cout << "G4LossTableManager::RetrievePhysicsTable: end; "
<< "all_tables_are_built= " << all_tables_are_built
<< G4endl;
}
}
@@ -354,8 +437,8 @@ void G4LossTableManager::RetrieveDEDXTable(const G4ParticleDefinition* aParticle
G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aParticle)
{
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables() for "
if(0 < verbose) {
G4cout << "G4LossTableManager::BuildTables() for "
<< aParticle->GetParticleName() << G4endl;
}
@@ -364,42 +447,41 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
list.clear();
G4std::vector<G4VEnergyLossSTD*> loss_list;
loss_list.clear();
G4VEnergyLossSTD* em = 0;
G4VEnergyLossSTD* em = 0;
G4int iem = 0;
G4bool no_el = true;
for(G4int i=0; i<n_loss; i++) {
if(aParticle == part_vector[i]) {
base_part_vector[i] = loss_vector[i]->BaseParticle();
for (G4int i=0; i<n_loss; i++) {
if (aParticle == part_vector[i]) {
loss_vector[i]->Initialise();
if(no_el && loss_vector[i]->SecondaryParticle() == theElectron) {
em = loss_vector[i];
iem= i;
no_el = false;
}
}
if(!em) {
em = loss_vector[i];
iem= i;
}
}
tables_are_built[i] = true;
list.push_back(loss_vector[i]->BuildDEDXTable());
loss_list.push_back(loss_vector[i]);
}
}
G4int n_dedx = list.size();
if(!n_dedx) return 0;
G4int n_dedx = list.size();
if (!n_dedx) return 0;
if(aParticle == theElectron) eIonisation = em;
if (aParticle == theElectron) eIonisation = em;
if(0 < verbose) {
if (1 < verbose) {
G4cout << "G4LossTableManager::BuildTables() start to build range tables"
<< " and the sum of " << n_dedx << " processes"
<< " and the sum of " << n_dedx << " processes"
<< G4endl;
}
G4PhysicsTable* dedx = list[0];
if(1 < n_dedx) {
if (1 < n_dedx) {
dedx = tableBuilder->BuildDEDXTable(list);
for(G4int i=0; i<n_dedx; i++) {
list[i]->clearAndDestroy();
@@ -415,14 +497,21 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
inv_range_vector[iem] = invrange;
loss_map[aParticle] = em;
for(G4int j=0; j<n_dedx; j++) {
if(loss_list[j]->SecondaryParticle() == theElectron) {
loss_list[j]->SetSecondaryRangeTable(eIonisation->RangeTable());
for (G4int j=0; j<n_dedx; j++) {
if(loss_list[j]->SecondaryParticle() == theElectron)
loss_list[j]->SetSecondaryRangeTable(eIonisation->RangeTable());
G4PhysicsTable* lambdaTable = loss_list[j]->BuildLambdaTable();
loss_list[j]->SetLambdaTable(lambdaTable);
if (0 < loss_list[j]->NumberOfSubCutoffRegions()) {
lambdaTable = loss_list[j]->BuildLambdaSubTable();
loss_list[j]->SetSubLambdaTable(lambdaTable);
}
}
if(1 < verbose) {
G4cout << "G4LossTableManager::BuildTables: Tables are built"
<< " for " << em->GetProcessName()
if (0 < verbose) {
G4cout << "G4LossTableManager::BuildTables: Tables are built for "
<< aParticle->GetParticleName()
<< "; ionisation process: " << em->GetProcessName()
<< G4endl;
}
return em;
@@ -430,7 +519,7 @@ G4VEnergyLossSTD* G4LossTableManager::BuildTables(const G4ParticleDefinition* aP
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetLossFluctuations(G4bool val)
void G4LossTableManager::SetLossFluctuations(G4bool val)
{
lossFluctuationFlag = val;
for(G4int i=0; i<n_loss; i++) {
@@ -440,7 +529,7 @@ void G4LossTableManager::SetLossFluctuations(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetSubCutoff(G4bool val)
void G4LossTableManager::SetSubCutoff(G4bool val)
{
subCutoffFlag = val;
for(G4int i=0; i<n_loss; i++) {
@@ -460,7 +549,7 @@ void G4LossTableManager::SetIntegral(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinSubRange(G4double val)
void G4LossTableManager::SetMinSubRange(G4double val)
{
minSubRange = val;
for(G4int i=0; i<n_loss; i++) {
@@ -480,7 +569,7 @@ void G4LossTableManager::SetRandomStep(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMinEnergy(G4double val)
void G4LossTableManager::SetMinEnergy(G4double val)
{
minKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
@@ -490,7 +579,7 @@ void G4LossTableManager::SetMinEnergy(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetMaxEnergy(G4double val)
void G4LossTableManager::SetMaxEnergy(G4double val)
{
maxKinEnergy = val;
for(G4int i=0; i<n_loss; i++) {
@@ -500,9 +589,9 @@ void G4LossTableManager::SetMaxEnergy(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
{
maxRangeVariation = v1;
maxRangeVariation = v1;
maxFinalStep = v2;
for(G4int i=0; i<n_loss; i++) {
loss_vector[i]->SetStepLimits(v1, v2);
@@ -511,47 +600,4 @@ void G4LossTableManager::SetStepLimits(G4double v1, G4double v2)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4LossTableManager::StorePhysicsTable(G4VEnergyLossSTD* el,
const G4String& dedx_file,
const G4String& range_file,
const G4String& inv_range_file,
G4bool ascii)
{
G4int i=0;
for(i=0; i<n_loss; i++) {
if(el == loss_vector[i]) break;
}
// store stopping power table
if (dedx_vector[i]) {
if ( !dedx_vector[i]->StorePhysicsTable(dedx_file, ascii) ){
G4cout << "Fatal error theDEDXTable->StorePhysicsTable in <"
<< dedx_file << ">"
<< G4endl;
return false;
}
}
if (range_vector[i]) {
if ( !range_vector[i]->StorePhysicsTable(range_file, ascii) ){
G4cout << "Fatal error theRangeTable->StorePhysicsTable in <"
<< range_file << ">"
<< G4endl;
return false;
}
}
if (inv_range_vector[i]) {
if ( !inv_range_vector[i]->StorePhysicsTable(inv_range_file, ascii) ){
G4cout << "Fatal error theInverseRangeTable->StorePhysicsTable in <"
<< inv_range_file << ">"
<< G4endl;
return false;
}
}
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4MultipleScattering.cc,v 1.30 2002/12/11 12:05:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScattering.cc,v 1.39 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
@@ -52,8 +52,14 @@
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 30-10-02 rename variable cm - Ecm, V.Ivanchenko
// 11-12-02 precision problem in ComputeTransportCrossSection
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured, L.Urban
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method
// 17-03-03 cut per region, V.Ivanchenko
// 13-04-03 add initialisation in GetContinuesStepLimit + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (M.Asai)
// -----------------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -64,13 +70,13 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScattering::G4MultipleScattering(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
fTransportMeanFreePath (1.e12),kappa(2.5),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
@@ -84,8 +90,10 @@ G4MultipleScattering::G4MultipleScattering(const G4String& processName)
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
pcz(0.17),zmean(0.),
range(1.0),T1(1.0),lambda1(-1.),cth1(1.),z1(1.e10),dtrl(0.15),
zmean(0.),samplez(true),
range(1.),T0(1.),T1(1.),lambda0(1.),lambda1(-1.),
Tlow(0.),alam(1.),blam(1.),dtrl(0.15),
lambdam(-1.),clam(1.),zm(1.),cthm(1.),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
@@ -110,12 +118,13 @@ void G4MultipleScattering::BuildPhysicsTable(
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
@@ -124,11 +133,15 @@ void G4MultipleScattering::BuildPhysicsTable(
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
}
// ..............................
Tlow = aParticleType.GetPDGMass();
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
classic_electr_radius;
@@ -143,13 +156,14 @@ void G4MultipleScattering::BuildPhysicsTable(
}
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
@@ -157,13 +171,14 @@ void G4MultipleScattering::BuildPhysicsTable(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume =
material->GetVecNbOfAtomsPerVolume();
const G4int NumberOfElements = material->GetNumberOfElements();
density = material->GetDensity();
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
@@ -194,6 +209,7 @@ void G4MultipleScattering::BuildPhysicsTable(
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::ComputeTransportCrossSection(
const G4ParticleDefinition& aParticleType,
G4double KineticEnergy,
@@ -314,11 +330,11 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// compute equivalent kinetic energy
// lambda depends on p*beta ....
G4double Mass = ParticleMass ;
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
(aParticleType.GetParticleName() != "e+") )
{
// TAU = Tkin/ParticleMass , tau = Tkin_scaled/electronmass
// p*beta = Mass*TAU*(TAU+2.)/(TAU+1.) =
@@ -434,15 +450,17 @@ G4double G4MultipleScattering::ComputeTransportCrossSection(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScattering::GetContinuousStepLimit(
const G4Track& track,
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double KineticEnergy,tau,z0,kz;
G4double tau,zt,cz,cz1,grej,grej0;
const G4double expmax = 100., ztmax = (2.*expmax+1.)/(2.*expmax+3.) ;
const G4double tmax = 1.e20*mm ;
G4bool isOut;
// this process is not a candidate for selection by default
@@ -450,20 +468,28 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
tPathLength = currentMinimumStep;
aMaterial = track.GetMaterial();
materialIndex = aMaterial->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
KineticEnergy = aParticle->GetKineticEnergy();
T0 = aParticle->GetKineticEnergy();
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
range = G4EnergyLossTables::GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial);
T0,couple);
//VI Initialisation at the beginning of the step
cthm = 1.;
lambda1 = -1.;
lambdam = -1.;
alam = range;
blam = 1.+alam/lambda0 ;
zm = 1.;
// special treatment near boundaries ?
if (boundary)
if (boundary && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
@@ -471,125 +497,165 @@ G4double G4MultipleScattering::GetContinuousStepLimit(
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
}
if(stepno > 1)
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
tlimit = facrange*lambda0 ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
else if(stepno > stepnolastmsc)
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
}
// do the true -> geom transformation
lambda1 = -1.;
z1 = 1.e10 ;
zmean = tPathLength;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
tau = tPathLength/lambda0 ;
if (tau < tausmall || range < currentMinimumStep) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = fTransportMeanFreePath*(1.-exp(-tau));
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
{
T1 = G4EnergyLossTables::GetPreciseEnergyFromRange(
aParticle->GetDefinition(),range-0.5*tPathLength,aMaterial);
aParticle->GetDefinition(),range-tPathLength,couple);
lambda1 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T1,isOut);
z1 = fTransportMeanFreePath*(1.-exp(-0.5*tau));
cth1 = exp(-0.5*tau);
zmean = z1 + lambda1*(1.-exp(-0.5*tPathLength/lambda1))*cth1;
if(T0 < Tlow)
alam = range ;
else
alam = lambda0*tPathLength/(lambda0-lambda1) ;
blam = 1.+alam/lambda0 ;
if(tPathLength/range < 2.*dtrl)
{
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
lambdam = -1. ;
}
else
{
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
if ((pcz > 0.) && (2.*zmean > tPathLength))
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
z0 = zmean+pcz*(tPathLength-zmean);
kz = (2.*zmean-tPathLength)/(z0-zmean)+1.;
if (G4UniformRand() < z0/tPathLength)
zPathLength = z0*exp(log(G4UniformRand())/kz);
else zPathLength = tPathLength-(tPathLength-z0)
*exp(log(1.-G4UniformRand())/kz);
}
else
{
zPathLength = zmean;
cz = 0.5*(3.*zt-1.)/(1.-zt) ;
if(tPathLength < exp(log(tmax)/(2.*cz)))
{
cz1 = 1.+cz ;
grej0 = exp(cz1*log(cz*tPathLength/cz1))/cz ;
do
{
zPathLength = tPathLength*exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(zPathLength))*(tPathLength-zPathLength)/grej0 ;
} while (grej < G4UniformRand()) ;
}
else zPathLength = zmean;
}
else zPathLength = zmean;
}
// protection against z > lambda
if(zPathLength > lambda0)
zPathLength = lambda0 ;
tLast = tPathLength;
zLast = zPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScattering::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
{
const G4Track& track,const G4Step& step)
{
// only a geom path->true path transformation is performed
fParticleChange.Initialize(track);
G4double geomPathLength = track.GetStepLength();
G4double truePathLength;
if (geomPathLength/fTransportMeanFreePath < tausmall)
truePathLength = geomPathLength;
else if(geomPathLength == zLast) truePathLength = tLast;
else
{
if (geomPathLength <= z1)
{
if (geomPathLength < fTransportMeanFreePath)
truePathLength = -fTransportMeanFreePath
*log(1.-geomPathLength/fTransportMeanFreePath);
else truePathLength = range;
G4double geomPathLength = step.GetStepLength();
lambda1 = -1.;
}
else
{
if ((geomPathLength-z1)/(cth1*lambda1) < 1.)
truePathLength = 0.5*tLast-lambda1
*log(1.-(geomPathLength-z1)/(cth1*lambda1));
else truePathLength = range;
}
}
G4double truePathLength = 0. ;
//VI change order of if operators
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
fParticleChange.SetTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -599,8 +665,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappapl1 = kappa+1., kappami1 = kappa-1. ;
G4bool isOut;
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
@@ -608,30 +673,31 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
// change direction first ( scattering )
G4double cth =1 ;
G4double tau = truestep/fTransportMeanFreePath;
if(KineticEnergy <= 0.)
;
else
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1.0 ;
G4double tau = truestep/lambda0 ;
if (tau < tausmall) cth = 1.;
else if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
if(lambda1 > 0.) tau = 0.5*tLast/lambda1
+(truestep-0.5*tLast)/fTransportMeanFreePath;
if(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double b = 1. ;
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
G4double ea,eaa,b1,bx,eb1,ebx,cnorm1,cnorm2,f1x0,f2x0,w ;
@@ -642,11 +708,11 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
@@ -659,7 +725,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
@@ -669,7 +735,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
@@ -697,10 +763,9 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
cth = b-b1*bx/exp(log(ebx-G4UniformRand()*(ebx-eb1))/(c-1.)) ;
}
else
cth = -1.+2.*G4UniformRand() ;
cth = -1.+2.*G4UniformRand() ;
}
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
@@ -716,13 +781,13 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
{
if (tau < tausmall) rmean = 0.;
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
else
{
@@ -733,7 +798,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
}
if (rmean>0.) rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.);
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.);
else rmean = 0.;
// for rmean > 0) only
@@ -751,7 +816,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
@@ -761,6 +826,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
}
}
}
}
return &fParticleChange;
}
@@ -779,7 +845,7 @@ G4VParticleChange* G4MultipleScattering::PostStepDoIt(
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
@@ -793,6 +859,32 @@ G4bool G4MultipleScattering::RetrievePhysicsTable(
const G4String& directory,
G4bool ascii)
{
// set values of some data members
G4String name = particle->GetParticleName();
if(name == "e-" || name == "e+")
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
// ..............................
Tlow = particle->GetPDGMass();
// delete theTransportMeanFreePathTable
if (theTransportMeanFreePathTable != 0) {
theTransportMeanFreePathTable->clearAndDestroy();
@@ -803,22 +895,25 @@ G4bool G4MultipleScattering::RetrievePhysicsTable(
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (name == "e-" || name == "mu+" || name == "proton") PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScattering::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
@@ -20,13 +20,13 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4MultipleScatteringSTD.cc,v 1.6 2002/12/11 12:05:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4MultipleScatteringSTD.cc,v 1.18 2003/04/28 15:31:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------------------------
// 16/05/01 value of cparm changed , L.Urban
// 18/05/01 V.Ivanchenko Clean up against Linux ANSI compilation
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 07/08/01 new methods Store/Retrieve PhysicsTable (mma)
// 23-08-01 new angle and z distribution,energy dependence reduced,
// Store,Retrieve methods commented out temporarily, L.Urban
// 27-08-01 in BuildPhysicsTable:aParticleType.GetParticleName()=="mu+" (mma)
@@ -52,8 +52,14 @@
// 15-10-02 temporary fix for proton scattering
// 30-10-02 modified angle distribution,mods in boundary algorithm,
// changes in data members, L.Urban
// 11-12-02 precision problem in ComputeTransportCrossSection
// 11-12-02 precision problem in ComputeTransportCrossSection
// for small Tkin/for heavy particles cured from L.Urban
// 20-01-03 Migrade to cut per region (V.Ivanchenko)
// 05-02-03 changes in data members, new sampling for geom.
// path length, step dependence reduced with new
// method (L.Urban)
// 13-04-03 add initialisation in GetContinuesStepLimit + change table size (V.Ivanchenko)
// 26-04-03 fix problems of retrieve tables (V.Ivanchenko)
//
// -----------------------------------------------------------------------------
//
@@ -65,13 +71,13 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "Randomize.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::G4MultipleScatteringSTD(const G4String& processName)
: G4VContinuousDiscreteProcess(processName),
theTransportMeanFreePathTable(0),
fTransportMeanFreePath (1.e12),kappa(2.5),
taubig(8.0),tausmall(1.e-14),taulim(1.e-5),
LowestKineticEnergy(0.1*keV),
HighestKineticEnergy(100.*TeV),
@@ -83,16 +89,18 @@ G4MultipleScatteringSTD::G4MultipleScatteringSTD(const G4String& processName)
facrange(0.199),tlimit(1.e10*mm),tlimitmin(1.e-7*mm),
cf(1.001),
stepno(0),stepnolastmsc(-1000000),nsmallstep(5),
laststep(0.),
laststep(0.),
valueGPILSelectionMSC(NotCandidateForSelection),
pcz(0.17),zmean(0.),
range(1.0),T1(1.0),lambda1(-1.),cth1(1.),z1(1.e10),dtrl(0.15),
zmean(0.),samplez(true),
range(1.),T0(1.),T1(1.),lambda0(1.),lambda1(-1.),
Tlow(0.),alam(1.),blam(1.),dtrl(0.15),
lambdam(-1.),clam(1.),zm(1.),cthm(1.),
fLatDisplFlag(true),
NuclCorrPar (0.0615),
FactPar(0.40),
facxsi(1.)
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4MultipleScatteringSTD::~G4MultipleScatteringSTD()
@@ -111,12 +119,13 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
{
// set values of some data members
if((aParticleType.GetParticleName() == "e-") ||
(aParticleType.GetParticleName() == "e+"))
(aParticleType.GetParticleName() == "e+"))
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 1.80 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
@@ -125,10 +134,13 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.42 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
}
Tlow = aParticleType.GetPDGMass();
// tables are built for MATERIALS
const G4double sigmafactor = twopi*classic_electr_radius*
@@ -144,13 +156,14 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
}
// create table
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theTransportMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
theTransportMeanFreePathTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t i=0; i<numOfCouples; i++)
{
// create physics vector and fill it
@@ -158,13 +171,14 @@ void G4MultipleScatteringSTD::BuildPhysicsTable(
LowestKineticEnergy,HighestKineticEnergy,TotBin);
// get elements in the material
const G4Material* material = (*theMaterialTable)[J];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* NbOfAtomsPerVolume =
material->GetVecNbOfAtomsPerVolume();
const G4int NumberOfElements = material->GetNumberOfElements();
density = material->GetDensity();
// loop for kinetic energy values
for (G4int i=0; i<TotBin; i++)
{
@@ -317,12 +331,12 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
G4double ParticleMass = aParticleType.GetPDGMass();
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// correction if particle .ne. e-/e+
// compute equivalent kinetic energy
// lambda depends on p*beta ....
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
if((aParticleType.GetParticleName() != "e-") &&
(aParticleType.GetParticleName() != "e+") )
{
G4double TAU = KineticEnergy/ParticleMass ;
G4double c = ParticleMass*TAU*(TAU+2.)/(electron_mass_c2*(TAU+1.)) ;
@@ -367,7 +381,7 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
corrnuclsize = exp(-FactPar*ParticleMass/KineticEnergy)*
(corrnuclsize-1.)+1.;
}
// interpolate in AtomicNumber and beta2
// get bin number in Z
G4int iZ = 14;
@@ -391,10 +405,10 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
T = Tdat[iT+1]; E = T + electron_mass_c2;
G4double b2big = T*(E+electron_mass_c2)/(E*E);
G4double ratb2 = (beta2-b2small)/(b2big-b2small);
G4double c1,c2,cc1,cc2,corr;
if (Charge < 0.)
{
{
c1 = celectron[iZ][iT];
c2 = celectron[iZ+1][iT];
cc1 = c1+ratZ*(c2-c1);
@@ -429,20 +443,21 @@ G4double G4MultipleScatteringSTD::ComputeTransportCrossSection(
return sigma;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
const G4Track& track,
const G4Track& track,
G4double,
G4double currentMinimumStep,
G4double&)
{
G4double zPathLength,tPathLength;
const G4DynamicParticle* aParticle;
G4Material* aMaterial;
G4double KineticEnergy,tau,z0,kz;
G4double tau,zt,cz,cz1,grej,grej0;
const G4double expmax = 100., ztmax = (2.*expmax+1.)/(2.*expmax+3.) ;
const G4double tmax = 1.e20*mm ;
G4bool isOut;
G4LossTableManager* theManager = G4LossTableManager::Instance();
@@ -452,20 +467,27 @@ G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
tPathLength = currentMinimumStep;
aMaterial = track.GetMaterial();
materialIndex = aMaterial->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
materialIndex = couple->GetIndex();
aParticle = track.GetDynamicParticle();
KineticEnergy = aParticle->GetKineticEnergy();
T0 = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
lambda0 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T0,isOut);
range = theManager->GetRange(aParticle->GetDefinition(),
KineticEnergy,aMaterial);
T0,couple);
//VI Initialisation at the beginning of the step
cthm = 1.;
lambda1 = -1.;
lambdam = -1.;
alam = range;
blam = 1.+alam/lambda0 ;
zm = 1.;
// special treatment near boundaries ?
if (boundary)
if (boundary && range >= currentMinimumStep)
{
// step limitation at boundary ?
stepno = track.GetCurrentStepNumber() ;
@@ -473,126 +495,169 @@ G4double G4MultipleScatteringSTD::GetContinuousStepLimit(
{
stepnolastmsc = -1000000 ;
tlimit = 1.e10 ;
}
}
if(stepno > 1)
if(stepno > 1)
{
if(track.GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary)
{
stepnolastmsc = stepno ;
// if : diff.treatment for small/not small Z
if(range > fTransportMeanFreePath)
if(range > lambda0)
tlimit = facrange*range ;
else
tlimit = facrange*fTransportMeanFreePath ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
tlimit = facrange*lambda0 ;
if(tlimit < tlimitmin) tlimit = tlimitmin ;
laststep = tlimit ;
if(tPathLength > tlimit)
if(tPathLength > tlimit)
{
tPathLength = tlimit ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
else if(stepno > stepnolastmsc)
{
if((stepno - stepnolastmsc) < nsmallstep)
if((stepno - stepnolastmsc) < nsmallstep)
{
if(tPathLength > tlimit)
{
laststep *= cf ;
tPathLength = laststep ;
valueGPILSelectionMSC = CandidateForSelection;
}
}
}
}
}
}
// do the true -> geom transformation
lambda1 = -1.;
z1 = 1.e10 ;
zmean = tPathLength;
tau = tPathLength/fTransportMeanFreePath ;
if(tau < tausmall) zPathLength = tPathLength;
tau = tPathLength/lambda0 ;
//G4cout << "StepLimit: tpl= " << tPathLength << " lambda0= " << lambda0
// << " range= " << range << " currentMinStep= " << currentMinimumStep << G4endl;
if(tau < tausmall || range < currentMinimumStep ) zPathLength = tPathLength;
else
{
if(tPathLength/range < dtrl) zmean = fTransportMeanFreePath*(1.-exp(-tau));
if(tPathLength/range < dtrl) zmean = lambda0*(1.-exp(-tau));
else
{
{
T1 = theManager->GetEnergy(
aParticle->GetDefinition(),range-0.5*tPathLength,aMaterial);
aParticle->GetDefinition(),range-tPathLength,couple);
lambda1 = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(T1,isOut);
z1 = fTransportMeanFreePath*(1.-exp(-0.5*tau));
cth1 = exp(-0.5*tau);
zmean = z1 + lambda1*(1.-exp(-0.5*tPathLength/lambda1))*cth1;
if(T0 < Tlow)
alam = range ;
else
alam = lambda0*tPathLength/(lambda0-lambda1) ;
blam = 1.+alam/lambda0 ;
if(tPathLength/range < 2.*dtrl)
{
zmean = alam*(1.-exp(blam*log(1.-tPathLength/alam)))/blam ;
lambdam = -1. ;
}
else
{
G4double w = 1.-0.5*tPathLength/alam ;
lambdam = lambda0*w ;
clam = 1.+alam/lambdam ;
cthm = exp(alam*log(w)/lambda0) ;
zm = alam*(1.-exp(blam*log(w)))/blam ;
zmean = zm + alam*(1.-exp(clam*log(w)))*cthm/clam ;
}
}
// sample z
if ((pcz > 0.) && (2.*zmean > tPathLength))
zt = zmean/tPathLength ;
if (samplez && (zt < ztmax) && (zt > 0.5))
{
z0 = zmean+pcz*(tPathLength-zmean);
kz = (2.*zmean-tPathLength)/(z0-zmean)+1.;
if (G4UniformRand() < z0/tPathLength)
zPathLength = z0*exp(log(G4UniformRand())/kz);
else zPathLength = tPathLength-(tPathLength-z0)
*exp(log(1.-G4UniformRand())/kz);
}
else
{
zPathLength = zmean;
cz = 0.5*(3.*zt-1.)/(1.-zt) ;
if(tPathLength < exp(log(tmax)/(2.*cz)))
{
cz1 = 1.+cz ;
grej0 = exp(cz1*log(cz*tPathLength/cz1))/cz ;
do
{
zPathLength = tPathLength*exp(log(G4UniformRand())/cz1) ;
grej = exp(cz*log(zPathLength))*(tPathLength-zPathLength)/grej0 ;
} while (grej < G4UniformRand()) ;
}
else zPathLength = zmean;
}
else zPathLength = zmean;
}
// protection against z > lambda
if(zPathLength > lambda0)
zPathLength = lambda0 ;
tLast = tPathLength;
zLast = zPathLength;
zLast = zPathLength;
return zPathLength;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VParticleChange* G4MultipleScatteringSTD::AlongStepDoIt(
const G4Track& track,const G4Step& Step)
{
const G4Track& track,const G4Step& step)
{
// only a geom path->true path transformation is performed
fParticleChange.Initialize(track);
G4double geomPathLength = track.GetStepLength();
G4double truePathLength;
if (geomPathLength/fTransportMeanFreePath < tausmall)
truePathLength = geomPathLength;
else if(geomPathLength == zLast) truePathLength = tLast;
else
{
if (geomPathLength <= z1)
{
if (geomPathLength < fTransportMeanFreePath)
truePathLength = -fTransportMeanFreePath
*log(1.-geomPathLength/fTransportMeanFreePath);
else truePathLength = range;
G4double geomPathLength = step.GetStepLength();
lambda1 = -1.;
}
else
{
if ((geomPathLength-z1)/(cth1*lambda1) < 1.)
truePathLength = 0.5*tLast-lambda1
*log(1.-(geomPathLength-z1)/(cth1*lambda1));
else truePathLength = range;
}
}
G4double truePathLength = 0. ;
if(geomPathLength == zLast) truePathLength = tLast;
else if(geomPathLength/lambda0 < tausmall) truePathLength = geomPathLength;
else
{
// G4cout << "alam= " << alam << " blam= " << blam << " lambda1= " << lambda1 << G4endl;
if(lambda1 < 0.) truePathLength = -lambda0*log(1.-geomPathLength/lambda0) ;
else if(lambdam < 0.)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = tLast;
}
else
{
if(geomPathLength <= zm)
{
if(blam*geomPathLength/alam < 1.)
truePathLength = alam*(1.-exp(log(1.-blam*geomPathLength/alam)/
blam)) ;
else
truePathLength = 0.5*tLast;
lambdam = -1. ;
}
else
{
//G4cout << "clam= " << clam << " zm= " << zm << " cthm= " << cthm << G4endl;
if(clam*(geomPathLength-zm)/(alam*cthm) < 1.)
truePathLength = 0.5*tLast + alam*(1.-
exp(log(1.-clam*(geomPathLength-zm)/(alam*cthm)))/clam) ;
else
truePathLength = tLast ;
}
}
// G4cout << "tLenth= " << truePathLength << " tpl= " << tLast << G4endl;
// protection ....
if(truePathLength > tLast)
truePathLength = tLast ;
}
//VI truePath length cannot be smaller than geomPathLength
if (truePathLength < geomPathLength) truePathLength = geomPathLength;
//G4cout << "AlongStep: trueLength= " << truePathLength << " geomLength= "
// << geomPathLength << " zlast= " << zLast << G4endl;
fParticleChange.SetTrueStepLength(truePathLength);
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -602,8 +667,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
const G4Step& stepData)
{
// angle distribution parameters
const G4double kappapl1 = kappa+1., kappami1 = kappa-1. ;
G4bool isOut;
const G4double kappa = 2.5, kappapl1 = kappa+1., kappami1 = kappa-1. ;
fParticleChange.Initialize(trackData);
G4double truestep = stepData.GetStepLength();
@@ -611,29 +675,31 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double KineticEnergy = aParticle->GetKineticEnergy();
fTransportMeanFreePath = (*theTransportMeanFreePathTable)
(materialIndex)->GetValue(KineticEnergy,isOut);
// change direction first ( scattering )
G4double cth =1 ;
G4double tau = truestep/fTransportMeanFreePath;
if(KineticEnergy <= 0.)
;
else
// do nothing for stopped particles !
if(KineticEnergy > 0.)
{
// change direction first ( scattering )
G4double cth = 1. ;
G4double tau = truestep/lambda0 ;
//G4cout << "tau= " << tau << " lambda1= " << lambda1 << " lambdam= " << lambdam << G4endl;
if (tau < tausmall) cth = 1.;
else if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
if(lambda1 > 0.) tau = 0.5*tLast/lambda1
+(truestep-0.5*tLast)/fTransportMeanFreePath;
if(lambda1 > 0.)
{
if(lambdam < 0.)
tau = -alam*log(1.-truestep/alam)/lambda0 ;
else
tau = -log(cthm)-alam*log(1.-(truestep-0.5*tLast)/alam)/lambdam ;
}
if(tau > taubig) cth = -1.+2.*G4UniformRand();
else
{
const G4double amax=25. ;
const G4double tau0 = 0.02 ;
const G4double b = 1. ;
G4double a,x0,c,xmean1,xmean2,
xmeanth,prob,qprob ;
@@ -645,11 +711,11 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
else
a = (alfa1+alfa3*w)/tau ;
x0 = 1.-xsi/a ;
x0 = 1.-xsi/a ;
if(x0 < 0.) x0 = 0. ;
// from continuity of the 1st derivatives
c = a*(b-x0) ;
c = a*(b-x0) ;
if(a*tau < c0)
c = c0*(b-x0)/tau ;
@@ -661,9 +727,8 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
ea = exp(-a*(1.-x0)) ;
else
ea = 0. ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
eaa = 1.-ea ;
xmean1 = 1.-1./a+(1.-x0)*ea/eaa ;
b1 = b+1. ;
bx=b-x0 ;
@@ -673,7 +738,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
xmeanth = exp(-tau) ;
cnorm1 = a/eaa ;
cnorm1 = a/eaa ;
cnorm2 = (c-1.)*eb1*ebx/(eb1-ebx) ;
f1x0 = cnorm1*exp(-a*(1.-x0)) ;
f2x0 = cnorm2/exp(c*log(b-x0)) ;
@@ -688,11 +753,18 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
if(qprob > 1.)
{
qprob = 1. ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
prob = (xmeanth-xmean2)/(xmean1-xmean2) ;
}
// *******************************************
// sampling of costheta
/*
G4cout << "tau= " << tau << " prob= " << prob << " qprob= " << qprob << G4endl;
G4cout << "ea= " << ea << " eaa= " << eaa << " a= " << a
<< " b= " << b << " b1= " << b1 << " bx= " << bx
<< " ebx= " << ebx << " eb1= " << eb1 << " c= " << c
<< G4endl;
*/
if(G4UniformRand() < qprob)
{
if(G4UniformRand() < prob)
@@ -704,12 +776,13 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
cth = -1.+2.*G4UniformRand() ;
}
}
}
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi), diry = sth*sin(phi), dirz = cth;
//G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << tLast << G4endl;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,dirz);
@@ -717,34 +790,35 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
fParticleChange.SetMomentumChange(newDirection.x(),
newDirection.y(),
newDirection.z());
if (fLatDisplFlag)
{
// compute mean lateral displacement, only for safety > tolerance !
// compute mean lateral displacement, only for safety > tolerance !
G4double safetyminustolerance = stepData.GetPostStepPoint()->GetSafety();
G4double rmean, etau;
if (safetyminustolerance > 0.)
G4double rmean = 0.0;
if (safetyminustolerance > 0. && tau>=tausmall)
{
if (tau < tausmall) rmean = 0.;
else if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau/4.)/6. ;
if(tau < taulim) rmean = kappa*tau*tau*tau*(1.-kappapl1*tau*0.25)/6. ;
else
{
G4double etau = 0.0;
if(tau<taubig) etau = exp(-tau);
else etau = 0.;
rmean = -kappa*tau;
rmean = -exp(rmean)/(kappa*kappami1);
rmean += tau-kappapl1/kappa+kappa*etau/kappami1;
//G4cout << "tau= " << tau << " lambda0= " << lambda0 << " etau= " << etau << " kappa= " << kappa << G4endl;
}
if (rmean>0.) rmean = 2.*fTransportMeanFreePath*sqrt(rmean/3.);
if (rmean>0.) rmean = 2.*lambda0*sqrt(rmean/3.0);
else rmean = 0.;
// for rmean > 0) only
if (rmean > 0.)
{
if (rmean>safetyminustolerance) rmean = safetyminustolerance;
//G4cout << "r= " << rmean << " safety= " << safetyminustolerance << G4endl;
// sample direction of lateral displacement
phi = twopi*G4UniformRand();
dirx = cos(phi); diry = sin(phi); dirz = 0.;
@@ -755,7 +829,7 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
// compute new endpoint of the Step
G4ThreeVector newPosition = stepData.GetPostStepPoint()->GetPosition()
+ rmean*latDirection;
G4Navigator* navigator =
G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
@@ -765,14 +839,14 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
}
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4MultipleScatteringSTD::StorePhysicsTable(G4ParticleDefinition* particle,
const G4String& directory,
const G4String& directory,
G4bool ascii)
{
G4String filename;
@@ -783,9 +857,9 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to store the PhysicsTables in "
<< ": Success to store the PhysicsTables in "
<< directory << G4endl;
return true;
}
@@ -794,9 +868,34 @@ G4VParticleChange* G4MultipleScatteringSTD::PostStepDoIt(
G4bool G4MultipleScatteringSTD::RetrievePhysicsTable(
G4ParticleDefinition* particle,
const G4String& directory,
const G4String& directory,
G4bool ascii)
{
// set values of some data members
G4String name = particle->GetParticleName();
if(name == "e-" || name == "e+")
{
// parameters for e+/e-
alfa1 = 1.45 ;
alfa2 = 0.60 ;
alfa3 = 0.30 ;
b = 1. ;
xsi = facxsi*2.22 ;
c0 = 2.30 ;
}
else
{
// parameters for heavy particles
alfa1 = 1.10 ;
alfa2 = 0.14 ;
alfa3 = 0.07 ;
b = 1. ;
xsi = facxsi*2.70 ;
c0 = 1.40 ;
}
Tlow = particle->GetPDGMass();
// delete theTransportMeanFreePathTable
if (theTransportMeanFreePathTable != 0) {
theTransportMeanFreePathTable->clearAndDestroy();
@@ -807,22 +906,25 @@ G4bool G4MultipleScatteringSTD::RetrievePhysicsTable(
// retreive mean free path table
filename = GetPhysicsTableFileName(particle,directory,"MeanFreePath",ascii);
theTransportMeanFreePathTable =
theTransportMeanFreePathTable =
new G4PhysicsTable(G4Material::GetNumberOfMaterials());
if (!theTransportMeanFreePathTable->RetrievePhysicsTable(filename, ascii) ){
G4cout << " FAIL theMeanFreePathTable->RetrievePhysicsTable in " << filename
<< G4endl;
<< G4endl;
return false;
}
G4cout << GetProcessName() << " for " << particle->GetParticleName()
<< ": Success to retrieve the PhysicsTables from "
<< directory << G4endl;
if (name == "e-" || name == "mu+" || name == "proton") PrintInfoDefinition();
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4MultipleScatteringSTD::PrintInfoDefinition()
{
G4String comments = " Tables of transport mean free paths.";
@@ -830,10 +932,14 @@ void G4MultipleScatteringSTD::PrintInfoDefinition()
comments += " displacement of the particle , too.";
G4cout << G4endl << GetProcessName() << ": " << comments
<< "\n PhysicsTables from "
<< "\n PhysicsTables from "
<< G4BestUnit(LowestKineticEnergy ,"Energy")
<< " to " << G4BestUnit(HighestKineticEnergy,"Energy")
<< " in " << TotBin << " bins. \n";
if(1 < verboseLevel) {
G4cout << "LambdaTable address= " << theTransportMeanFreePathTable << G4endl;
if(theTransportMeanFreePathTable) G4cout << (*theTransportMeanFreePathTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -29,10 +29,16 @@
// File name: G4SCProcessorStand
//
// Author: Vladimir Ivanchenko
//
//
// Creation date: 10.05.2002
//
// Modifications: 09.12.2002 VI remove warning
// Modifications:
//
// 09-12-02 remove warning (V.Ivanchenko)
// 23-12-02 change interface in order to move to cut per region (V.Ivanchenko)
// 26-12-02 Secondary production moved to derived classes (V.Ivanchenko)
// 27-01-03 Make models region aware (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
//
// -------------------------------------------------------------------
@@ -46,73 +52,63 @@
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4EmModelManager.hh"
#include "G4MaterialTable.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4VEmModel.hh"
#include "Randomize.hh"
#include "G4Step.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::G4SCProcessorStand()
: G4VSubCutoffProcessor(),
G4SCProcessorStand::G4SCProcessorStand(const G4String& nam)
: G4VSubCutoffProcessor(nam),
theLambdaSubTable(0),
thePositron(G4Positron::Positron()),
modelManager(0)
thePositron(G4Positron::Positron())
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4SCProcessorStand::~G4SCProcessorStand()
{
if(theLambdaSubTable) theLambdaSubTable->clearAndDestroy();
}
G4SCProcessorStand::~G4SCProcessorStand()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4SCProcessorStand::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4EmModelManager* m)
const G4ParticleDefinition* sp,
const G4DataVector* vCuts,
const G4DataVector* vSubCuts)
{
particle = p;
secondaryParticle = sp;
modelManager = m;
navigator = (G4TransportationManager::GetTransportationManager())
->GetNavigatorForTracking();
theCuts = modelManager->Cuts();
theSubCuts = modelManager->Cuts();
theCuts = vCuts;
theSubCuts = vSubCuts;
initialMass= particle->GetPDGMass();
// Access to materials
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
rangeCuts.clear();
for(size_t i=0; i<nMaterials; i++) {
const G4Material* aMaterial = (*theMaterialTable)[i];
rangeCuts.push_back(secondaryParticle->GetRangeThreshold(aMaterial));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step,
const G4DynamicParticle* dp,
G4double meanLoss)
G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondaries(
const G4Step& step,
G4double& tmax,
G4double& meanLoss,
G4VEmModel* currentModel)
{
G4bool b;
const G4Material* mat = (step.GetTrack())->GetMaterial();
const G4Track* track = step.GetTrack();
const G4MaterialCutsCouple* couple = track->GetMaterialCutsCouple();
if(mat != material) {
material = mat;
materialIndex = material->GetIndex();
cut = (*theCuts)[materialIndex];
subcut = (*theSubCuts)[materialIndex];
rcut = rangeCuts[materialIndex];
}
size_t index = couple->GetIndex();
G4double subcut = (*theSubCuts)[index];
if(subcut >= cut) return 0;
if(subcut >= tmax) return 0;
G4double cut = (*theCuts)[index];
G4double rcut = couple->GetProductionCuts()->GetProductionCut(1);
const G4DynamicParticle* dp = track->GetDynamicParticle();
G4double ekin = dp->GetKineticEnergy();
G4double effChargeFactor = 1.0;
G4double massRatio = 1.0;
@@ -123,9 +119,9 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
massRatio = initialMass/mass;
G4double q = particle->GetPDGCharge()/dp->GetCharge();
effChargeFactor = q*q;
}
}
G4double cross = (*theLambdaSubTable)[materialIndex]->GetValue(ekin*massRatio, b);
G4double cross = (*theLambdaSubTable)[index]->GetValue(ekin*massRatio, b);
if(0.0 >= cross) return 0;
@@ -135,7 +131,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
G4double postsafety = navigator->ComputeSafety(postpoint);
G4double safety = G4std::min(presafety,postsafety);
if(safety >= rcut) return 0;
G4ThreeVector prepoint = pre->GetPosition();
G4ThreeVector dr = postpoint - prepoint;
@@ -145,7 +141,6 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
G4double length = step.GetStepLength();
G4double inv_v = (ekin + mass)/(c_light*dp->GetTotalMomentum());
G4VEmModel* currentModel = modelManager->SelectModel(ekin);
G4std::vector<G4Track*>* vtr = new G4std::vector<G4Track*>;
do {
@@ -153,10 +148,10 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
G4double del = G4UniformRand()*effChargeFactor / cross;
fragment += del/length;
if (fragment > 1.0) break;
dt += del * inv_v;
G4std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondary(material, dp, subcut, cut);
dt += del * inv_v;
G4std::vector<G4DynamicParticle*>* newp =
currentModel->SampleSecondaries(couple, dp, subcut, cut);
if (newp) {
G4DynamicParticle* p;
@@ -183,7 +178,7 @@ G4std::vector<G4Track*>* G4SCProcessorStand::SampleSecondary(const G4Step& step
return vtr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -33,6 +33,10 @@
//
// Modifications:
//
// 28-12-02 add method Dispersion (V.Ivanchenko)
// 07-02-03 change signature (V.Ivanchenko)
// 13-02-03 Add name (V.Ivanchenko)
//
// Class Description:
//
// -------------------------------------------------------------------
@@ -51,8 +55,8 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4UniversalFluctuation::G4UniversalFluctuation()
:G4VEmFluctuationModel(),
G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
:G4VEmFluctuationModel(nam),
minNumberInteractionsBohr(10.0),
theBohrBeta2(50.0*keV/proton_mass_c2),
minLoss(0.000001*eV),
@@ -74,94 +78,67 @@ G4UniversalFluctuation::~G4UniversalFluctuation()
void G4UniversalFluctuation::Initialise(const G4ParticleDefinition* part)
{
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
particle = part;
particleMass = part->GetPDGMass();
G4double q = part->GetPDGCharge()/eplus;
chargeSquare = q*q;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double meanLoss)
G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length,
G4double& meanLoss)
{
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same
// The model used to get the fluctuation is essentially the same
// as in Glandz in Geant3.
// shortcut for very very small loss
if(meanLoss < minLoss) return;
G4double preStepKinEnergy = dp->GetKineticEnergy();
if(meanLoss < minLoss) return meanLoss;
if(dp->GetDefinition() != particle) {
particleMass = dp->GetMass();
G4double q = dp->GetCharge();
chargeSquare = q*q;
particleMass = dp->GetMass();
G4double q = dp->GetCharge();
chargeSquare = q*q;
}
// data members for a given material
if(material != lastMaterial) {
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
electronDensity = material->GetElectronDensity();
// zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
}
// get particle data
G4double tau = preStepKinEnergy/particleMass;
G4double tau1 = tau + 1.0;
G4double tau2 = tau * (tau+2.0);
G4double beta2 = tau2/(tau1*tau1);
ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy();
G4double gam = (dp->GetKineticEnergy())/particleMass + 1.0;
G4double gam2 = gam*gam;
G4double beta2 = 1.0 - 1.0/gam2;
// Validity range for delta electron cross section
G4double loss, siga;
// Gaussian fluctuation
if(meanLoss >= minNumberInteractionsBohr*tmax || tmax <= ipotFluct*minNumberInteractionsBohr)
{
siga = tmax * (1.0-0.5*beta2) * length * twopi_mc2_rcl2
* electronDensity / beta2;
siga = sqrt(siga * chargeSquare);
/*
// High velocity or negatively charged particle
if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
siga = sqrt( siga * chargeSquare ) ;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
} else {
G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
siga = sqrt( siga * (chargeSquare * chu + yang)) ;
}
*/
electronDensity = material->GetElectronDensity();
siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare ;
siga = sqrt(siga);
do {
loss = G4RandGauss::shoot(meanLoss,siga);
} while (loss < 0.);
} while (loss < 0. || loss > 2.*meanLoss);
meanLoss = loss;
if(lastMaterial != material) lastMaterial = material;
return;
return loss;
}
// Non Gaussian fluctuation
if(material != lastMaterial) {
zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
f1Fluct = material->GetIonisation()->GetF1fluct();
f2Fluct = material->GetIonisation()->GetF2fluct();
e1Fluct = material->GetIonisation()->GetEnergy1fluct();
e2Fluct = material->GetIonisation()->GetEnergy2fluct();
e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
rateFluct = material->GetIonisation()->GetRateionexcfluct();
ipotLogFluct= material->GetIonisation()->GetLogMeanExcEnergy();
f1Fluct = material->GetIonisation()->GetF1fluct();
f2Fluct = material->GetIonisation()->GetF2fluct();
e1Fluct = material->GetIonisation()->GetEnergy1fluct();
e2Fluct = material->GetIonisation()->GetEnergy2fluct();
e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
rateFluct = material->GetIonisation()->GetRateionexcfluct();
ipotLogFluct = material->GetIonisation()->GetLogMeanExcEnergy();
lastMaterial = material;
}
@@ -173,7 +150,7 @@ void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
G4double dp3;
w1 = tmax/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
w2 = log(2.*electron_mass_c2*(gam2 - 1.0));
C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
@@ -315,7 +292,43 @@ void G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
}
}
meanLoss = loss;
return loss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4UniversalFluctuation::Dispersion(
const G4Material* material,
const G4DynamicParticle* dp,
G4double& tmax,
G4double& length)
{
electronDensity = material->GetElectronDensity();
G4double gam = (dp->GetKineticEnergy())/particleMass + 1.0;
G4double beta2 = 1.0 - 1.0/(gam*gam);
G4double siga = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
* electronDensity * chargeSquare;
return siga;
}
/*
// High velocity or negatively charged particle
zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume());
if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
siga = sqrt( siga * chargeSquare ) ;
// Low velocity - additional ion charge fluctuations according to
// Q.Yang et al., NIM B61(1991)149-155.
} else {
G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
siga = sqrt( siga * (chargeSquare * chu + yang)) ;
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VEnergyLoss.cc,v 1.33 2002/07/22 10:55:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4VEnergyLoss.cc,v 1.40 2003/04/04 14:33:34 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
@@ -32,21 +32,26 @@
// bug fixed in fluct., L.Urban 22/11/00
// bugfix in fluct.
// (some variables are doubles instead of ints now),L.Urban 23/03/01
// 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation
// 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation
// 17-09-01 migration of Materials to pure STL (mma)
// 26-10-01 static inline functions moved from .hh file (mma)
// 26-10-01 static inline functions moved from .hh file (mma)
// 08.11.01 some static methods,data members are not static L.Urban
// 11.02.02 subSecFlag = false --> No sucutoff generation (mma)
// 11.02.02 subSecFlag = false --> No sucutoff generation (mma)
// 14.02.02 initial value of data member finalRange has been changed L.Urban
// 26.02.02 initial value of data member finalRange = 1 mm (mma)
// 21.07.02 V.Ivanchenko Fix at low energies - if tmax below ionisation
// 21.07.02 V.Ivanchenko Fix at low energies - if tmax below ionisation
// potential then only Gaussian fluctuations are sampled.
//
// 15.01.03 Migrade to cut per region (V.Ivanchenko)
// 05.02.03 Minor fix for several region case (V.Ivanchenko)
// 25.03.03 add finalRangeRequested (mma)
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4ProductionCutsTable.hh"
#include "G4LossTableManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -61,6 +66,7 @@ G4bool G4VEnergyLoss::setMinDeltaCutInRange = false;
G4double G4VEnergyLoss::dRoverRange = 20*perCent;
G4double G4VEnergyLoss::finalRange = 1*mm;
G4double G4VEnergyLoss::finalRangeRequested = -1*mm;
G4double G4VEnergyLoss::c1lim = dRoverRange;
G4double G4VEnergyLoss::c2lim = 2.*(1.-dRoverRange)*finalRange;
G4double G4VEnergyLoss::c3lim = -(1.-dRoverRange)*finalRange*finalRange;
@@ -86,8 +92,9 @@ G4VEnergyLoss::G4VEnergyLoss(const G4String& aName , G4ProcessType aType)
nmaxCont1(4),
nmaxCont2(16)
{
//create (only once) EnergyLoss messenger
if(!ELossMessenger) ELossMessenger = new G4EnergyLossMessenger();
//create (only once) EnergyLoss messenger
// if(!ELossMessenger) ELossMessenger = new G4EnergyLossMessenger();
if(!ELossMessenger) ELossMessenger = G4LossTableManager::Instance()->GetMessenger();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -125,20 +132,20 @@ void G4VEnergyLoss::SetMinDeltaCutInRange(G4double value)
void G4VEnergyLoss::SetStepFunction(G4double c1, G4double c2)
{
dRoverRange = c1; finalRange = c2;
dRoverRange = c1; finalRangeRequested = c2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
c2lim=2.*(1-dRoverRange)*finalRangeRequested;
c3lim=-(1.-dRoverRange)*finalRangeRequested*finalRangeRequested;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4double LowestKineticEnergy,G4double HighestKineticEnergy,G4int TotBin)
// Build range table from the energy loss table
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theRangeTable)
{ theRangeTable->clearAndDestroy();
@@ -147,7 +154,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
aVector = new G4PhysicsLogVector(LowestKineticEnergy,
@@ -158,7 +165,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
theRangeTable->insert(aVector);
}
return theRangeTable ;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -373,15 +380,15 @@ G4PhysicsTable* G4VEnergyLoss::BuildLabTimeTable(G4PhysicsTable* theDEDXTable,
G4double HighestKineticEnergy,G4int TotBin)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theLabTimeTable)
{ theLabTimeTable->clearAndDestroy();
delete theLabTimeTable; }
theLabTimeTable = new G4PhysicsTable(numOfMaterials);
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
@@ -403,17 +410,17 @@ G4PhysicsTable* G4VEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXTable
G4PhysicsTable* theProperTimeTable,
G4double LowestKineticEnergy,
G4double HighestKineticEnergy,G4int TotBin)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theDEDXTable->length();
if(theProperTimeTable)
{ theProperTimeTable->clearAndDestroy();
delete theProperTimeTable; }
theProperTimeTable = new G4PhysicsTable(numOfMaterials);
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
G4PhysicsLogVector* aVector;
@@ -629,7 +636,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRangeTa
{
G4double SmallestRange,BiggestRange ;
G4bool isOut ;
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
size_t numOfMaterials = theRangeTable->length();
if(theInverseRangeTable)
{ theInverseRangeTable->clearAndDestroy();
@@ -637,7 +644,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRangeTa
theInverseRangeTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfMaterials; J++)
{
SmallestRange = (*theRangeTable)(J)->
GetValue(LowestKineticEnergy,isOut) ;
@@ -723,7 +730,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "A"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffATable)
{ theRangeCoeffATable->clearAndDestroy();
@@ -784,7 +791,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "B"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffBTable)
{ theRangeCoeffBTable->clearAndDestroy();
@@ -844,7 +851,7 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRangeTab
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "C"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfMaterials = theRangeTable->length();
if(theRangeCoeffCTable)
{ theRangeCoeffCTable->clearAndDestroy();
@@ -898,27 +905,27 @@ G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRangeTab
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
const G4MaterialCutsCouple* couple,
G4double ChargeSquare,
G4double MeanLoss,
G4double step )
// calculate actual loss from the mean loss
// The model used to get the fluctuation is essentially the same as in Glandz in Geant3.
{
const G4double minLoss = 1.*eV ;
const G4double probLim = 0.01 ;
const G4double sumaLim = -log(probLim) ;
const G4double alim=10.;
const G4double kappa = 10. ;
const G4double factor = twopi_mc2_rcl2 ;
const G4double minLoss = 1.*eV ;
const G4double probLim = 0.01 ;
const G4double sumaLim = -log(probLim) ;
const G4double alim=10.;
const G4double kappa = 10. ;
const G4double factor = twopi_mc2_rcl2 ;
const G4Material* aMaterial = couple->GetMaterial();
// check if the material has changed ( cache mechanism)
if (aMaterial != lastMaterial)
{
lastMaterial = aMaterial;
imat = aMaterial->GetIndex();
imat = couple->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
@@ -938,14 +945,15 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double dp3;
G4double siga ;
// shortcut for very very small loss
// shortcut for very very small loss
if(MeanLoss < minLoss) return MeanLoss ;
// get particle data
G4double Tkin = aParticle->GetKineticEnergy();
ParticleMass = aParticle->GetMass() ;
threshold =((G4Electron::Electron())->GetEnergyCuts())[imat];
threshold = (*((G4ProductionCutsTable::GetProductionCutsTable())
->GetEnergyCutsVector(1)))[imat];
G4double rmass = electron_mass_c2/ParticleMass;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
@@ -1058,7 +1066,7 @@ G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
loss = p1*e1Fluct+p2*e2Fluct;
// smearing to avoid unphysical peaks
if(p2 > 0)
loss += (1.-2.*G4UniformRand())*e2Fluct;
loss += (1.-2.*G4UniformRand())*e2Fluct;
else if (loss>0.)
loss += (1.-2.*G4UniformRand())*e1Fluct;
@@ -1124,7 +1132,7 @@ G4bool G4VEnergyLoss::EqualCutVectors( G4double* vec1, G4double* vec2 )
for (size_t j=0; flag && j<G4Material::GetNumberOfMaterials(); j++){
flag = (vec1[j] == vec2[j]);
}
return flag;
}
@@ -1141,3 +1149,21 @@ G4double* G4VEnergyLoss::CopyCutVectors( G4double* dest, G4double* source )
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4VEnergyLoss::CutsWhereModified()
{
G4bool wasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
wasModified = true;
break;
}
}
return wasModified;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,339 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4VMultipleScattering
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 25.03.2003
//
// Modifications: 13.04.03 Change printout (V.Ivanchenko)
//
//
// Class Description:
//
// It is the generic process of multiple scattering it includes common
// part of calculations for all charged particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VMultipleScattering.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4VEmFluctuationModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
#include "G4PhysicsLogVector.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
navigator(0),
theLambdaTable(0),
currentCouple(0),
nBins(110),
minKinEnergy(1.0*eV),
maxKinEnergy(100.0*GeV),
boundary(false),
latDisplasment(true),
buildLambdaTable(true)
{
modelManager = new G4EmModelManager();
(G4LossTableManager::Instance())->Register(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::~G4VMultipleScattering()
{
(G4LossTableManager::Instance())->DeRegister(this);
delete modelManager;
if (theLambdaTable) {
theLambdaTable->clearAndDestroy();
delete theLambdaTable;
}
(G4LossTableManager::Instance())->DeRegister(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
{
currentCouple = 0;
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
G4bool cutsWasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
cutsWasModified = true;
break;
}
}
if( !cutsWasModified ) return;
InitialiseProcess(part);
if(latDisplasment) navigator = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
modelManager->Clear();
const G4DataVector* theCuts = modelManager->Initialise(&part, 0, 10.0, verboseLevel);
if (buildLambdaTable) {
theLambdaTable = new G4PhysicsTable(numOfCouples);
for (size_t i=0; i<numOfCouples; i++) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
G4PhysicsVector* aVector = PhysicsVector(couple);
modelManager->FillLambdaVector(aVector, couple, false);
// Insert vector for this material into the table
theLambdaTable->insert(aVector) ;
}
if(0 < verboseLevel) {
G4cout << "Lambda table is built for "
<< part.GetParticleName()
<< G4endl;
}
if(2 < verboseLevel) G4cout << *theLambdaTable << G4endl;
if(5 < verboseLevel) G4cout << theCuts << G4endl;
}
G4String num = part.GetParticleName();
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() done for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* p,
const G4Region* region)
{
G4VEmFluctuationModel* fm = 0;
modelManager->AddEmModel(order, p, fm, region);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
fParticleChange.Initialize(track);
G4double kineticEnergy = track.GetKineticEnergy();
G4double truestep = step.GetStepLength();
if (kineticEnergy > 0.0) {
G4double cth = currentModel->SampleCosineTheta(truestep);
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi);
G4double diry = sth*sin(phi);
G4ThreeVector oldDirection = track.GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,cth);
newDirection.rotateUz(oldDirection);
fParticleChange.SetMomentumChange(newDirection);
/*
if(0 < verboseLevel) {
const G4ParticleDefinition* pd = dynParticle->GetDefinition();
G4cout << "G4VMultipleScattering::PostStepDoIt: Sample secondary; E= " << finalT/MeV
<< " MeV; model= (" << currentModel->LowEnergyLimit(pd)
<< ", " << currentModel->HighEnergyLimit(pd) << ")"
<< G4endl;
}
*/
// G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << truePathLength << G4endl;
if (latDisplasment) {
G4double safety = step.GetPostStepPoint()->GetSafety();
if ( safety > 0.0) {
G4double r = currentModel->SampleDisplacement();
if (r > safety) r = safety;
// G4cout << "r= " << r << " safety= " << safety << G4endl;
// sample direction of lateral displacement
G4double phi = twopi*G4UniformRand();
G4double dirx = cos(phi);
G4double diry = sin(phi);
G4ThreeVector latDirection(dirx,diry,0.0);
latDirection.rotateUz(oldDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = (step.GetPostStepPoint())->GetPosition()
+ r*latDirection;
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.SetPositionChange(newPosition);
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::PrintInfoDefinition() const
{
G4cout << G4endl << GetProcessName() << ": Model variant of multiple scattering " << G4endl;
if (theLambdaTable) {
G4cout << " Lambda tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << nBins << " bins."
<< G4endl;
}
if (1 < verboseLevel) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VMultipleScattering::PhysicsVector(const G4MaterialCutsCouple* couple)
{
G4int nbins = 3;
//G4int nbins = nDEDXBins;
if( couple->IsUsed() ) nbins = nBins;
// G4double xmax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nbins);
return v;
}
G4bool G4VMultipleScattering::StorePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
G4bool res = true;
if ( theLambdaTable ) {
const G4String name = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
G4bool yes = theLambdaTable->StorePhysicsTable(name,ascii);
if( !yes ) res = false;
}
if ( res ) {
G4cout << "Physics table are stored for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
} else {
G4cout << "Fail to store Physics Table for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4VMultipleScattering::RetrievePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::RetrievePhysicsTable() for "
<< part->GetParticleName() << " and process "
<< GetProcessName() << G4endl;
}
G4bool res = true;
if(!buildLambdaTable) return res;
G4String num = part->GetParticleName();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4String filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
theLambdaTable = new G4PhysicsTable(numOfCouples);
res = theLambdaTable->RetrievePhysicsTable(filename,ascii);
if ( res ) {
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " is retrieved from <"
<< filename << ">"
<< G4endl;
}
} else {
theLambdaTable->clearAndDestroy();
theLambdaTable = 0;
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
}
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....