Import Geant4 0.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-01 15:25:35 +02:00
parent 54d6b71f95
commit b97f8d0df7
3237 changed files with 807095 additions and 0 deletions
@@ -0,0 +1,31 @@
# $Id: GNUmakefile,v 2.3 1998/07/10 23:02:09 gcosmo Exp $
# --------------------------------------------------------------------
# GNUmakefile for electromagnetic sub-library. John Allison, 25/6/98.
# --------------------------------------------------------------------
name := G4xrays
ifndef G4INSTALL
G4INSTALL = ../../../..
endif
include $(G4INSTALL)/config/architecture.gmk
CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/global/HEPRandom/include \
-I$(G4BASE)/global/HEPGeometry/include \
-I$(G4BASE)/geometry/management/include \
-I$(G4BASE)/geometry/magneticfield/include \
-I$(G4BASE)/geometry/volumes/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/management/include \
-I$(G4BASE)/particles/management/include \
-I$(G4BASE)/particles/bosons/include \
-I$(G4BASE)/particles/leptons/include \
-I$(G4BASE)/particles/hadrons/barions/include \
-I$(G4BASE)/particles/hadrons/mesons/include \
-I$(G4BASE)/particles/hadrons/ions/include \
-I$(G4BASE)/materials/include
include $(G4INSTALL)/config/common.gmk
@@ -0,0 +1,167 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4Cerenkov.hh,v 2.2 1998/08/25 22:05:48 gum Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
////////////////////////////////////////////////////////////////////////
// Cerenkov Radiation Class Definition
////////////////////////////////////////////////////////////////////////
//
// File: G4Cerenkov.hh
// Description: Continuous Process -- Generation of Cerenkov Photons
// Version: 2.0
// Created: 1996-02-21
// Author: Juliet Armstrong
// Updated: 1997-04-09 by Peter Gumplinger
// > G4MaterialPropertiesTable; new physics/tracking scheme
// mail: gum@triumf.ca
//
////////////////////////////////////////////////////////////////////////
#ifndef G4Cerenkov_h
#define G4Cerenkov_h 1
/////////////
// Includes
/////////////
#include "globals.hh"
#include "templates.hh"
#include "Randomize.hh"
#include "G4ThreeVector.hh"
#include "G4ParticleMomentum.hh"
#include "G4Step.hh"
#include "G4VContinuousProcess.hh"
#include "G4OpticalPhoton.hh"
#include "G4DynamicParticle.hh"
#include "G4Material.hh"
#include "G4PhysicsTable.hh"
#include "G4MaterialPropertiesTable.hh"
#include "G4PhysicsOrderedFreeVector.hh"
/////////////////////
// Class Definition
/////////////////////
class G4Cerenkov : public G4VContinuousProcess
{
private:
//////////////
// Operators
//////////////
// G4Cerenkov& operator=(const G4Cerenkov &right);
public:
////////////////////////////////
// Constructors and Destructor
////////////////////////////////
G4Cerenkov(const G4String& processName = "Cerenkov");
// G4Cerenkov(const G4Cerenkov &right);
~G4Cerenkov();
////////////
// Methods
////////////
G4bool IsApplicable(const G4ParticleDefinition& aParticleType);
G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double ,
G4double ,
G4double& );
G4VParticleChange* AlongStepDoIt(const G4Track& aTrack,
const G4Step& aStep);
void SetTrackSecondariesFirst(const G4bool state);
void SetMaxNumPhotonsPerStep(const G4int NumPhotons);
G4PhysicsTable* GetPhysicsTable() const;
// Returns the address of the physics table.
void DumpPhysicsTable() const;
private:
void BuildThePhysicsTable();
/////////////////////
// Helper Functions
/////////////////////
G4double GetAverageNumberOfPhotons(const G4DynamicParticle *aParticle,
const G4Material *aMaterial,
const G4MaterialPropertyVector* Rindex) const;
///////////////////////
// Class Data Members
///////////////////////
protected:
G4PhysicsTable* thePhysicsTable;
// A Physics Table can be either a cross-sections table or
// an energy table (or can be used for other specific
// purposes).
private:
G4bool fTrackSecondariesFirst;
G4int fMaxPhotons;
};
////////////////////
// Inline methods
////////////////////
inline
G4bool G4Cerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
{
return (aParticleType.GetPDGCharge() != 0);
}
inline
void G4Cerenkov::SetTrackSecondariesFirst(const G4bool state)
{
fTrackSecondariesFirst = state;
}
inline
void G4Cerenkov::SetMaxNumPhotonsPerStep(const G4int NumPhotons)
{
fMaxPhotons = NumPhotons;
}
inline
void G4Cerenkov::DumpPhysicsTable() const
{
G4int PhysicsTableSize = thePhysicsTable->entries();
G4PhysicsOrderedFreeVector *v;
for (G4int i = 0 ; i < PhysicsTableSize ; i++ )
{
v = (G4PhysicsOrderedFreeVector*)(*thePhysicsTable)[i];
v->DumpValues();
}
}
inline G4PhysicsTable* G4Cerenkov::GetPhysicsTable() const
{
return thePhysicsTable;
}
#endif /* G4Cerenkov_h */
@@ -0,0 +1,168 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4ForwardXrayTR.hh,v 2.1 1998/11/27 13:34:54 grichine Exp $
// GEANT4 tag $Name: geant4-00 $
//
// G4ForwardXrayTR -- header file
//
// Class for description of forward X-ray transition radiation generated
// by relativistic charged particle crossed interface between material 1
// and material 2 (1 -> 2)
//
// GEANT 4 class header file --- Copyright CERN 1995
// CERB Geneva Switzerland
//
// for information related to this code, please, contact
// CERN, CN Division, ASD Group
// History:
// 22.09.97, V. Grichine (Vladimir.Grichine@cern.ch)
#ifndef G4FORWARDXRAYTR_H
#define G4FORWARDXRAYTR_H
#include "globals.hh"
#include "templates.hh"
#include "geomdefs.hh"
#include "Randomize.hh"
#include "G4Step.hh"
#include "G4VDiscreteProcess.hh"
#include "G4DynamicParticle.hh"
#include "G4Material.hh"
#include "G4LogicalBorderSurface.hh"
#include "G4LogicalSkinSurface.hh"
#include "G4OpticalSurface.hh"
#include "G4OpticalPhoton.hh"
#include "G4TransportationManager.hh"
#include "G4TransitionRadiation.hh"
#include "G4PhysicsTable.hh"
#include "G4Gamma.hh"
class G4ForwardXrayTR : public G4TransitionRadiation
{
public:
// Constructors
G4ForwardXrayTR() ;
G4ForwardXrayTR( G4Material* pMat1,
G4Material* pMat2,
const G4String& processName="XrayTR" ) ;
// G4ForwardXrayTR(const G4ForwardXrayTR& right) ;
// Destructor
~G4ForwardXrayTR() ;
// Operators
// G4ForwardXrayTR& operator=(const G4ForwardXrayTR& right) ;
// G4int operator==(const G4ForwardXrayTR& right)const ;
// G4int operator!=(const G4ForwardXrayTR& right)const ;
/////////////////////// Methods /////////////////////////////////
//
G4VParticleChange* PostStepDoIt( const G4Track& aTrack,
const G4Step& aStep ) ;
G4double GetEnergyTR(G4int iMat, G4int jMat, G4int iTkin) const ;
G4double GetThetaTR(G4int iMat, G4int jMat, G4int iTkin) const ;
///////////////////// Angle distribution /////////////////////////////
//
G4double SpectralAngleTRdensity( G4double energy,
G4double varAngle ) const;
G4double AngleDensity( G4double energy,
G4double varAngle ) const ;
G4double EnergyInterval( G4double energy1,
G4double energy2,
G4double varAngle ) const ;
G4double AngleSum( G4double varAngle1,
G4double varAngle2 ) const ;
///////////////////////// Energy distribution ///////////////////////////////
G4double SpectralDensity( G4double energy,
G4double x ) const ;
G4double AngleInterval( G4double energy,
G4double varAngle1,
G4double varAngle2 ) const ;
G4double EnergySum( G4double energy1,
G4double energy2 ) const ;
/////////////////////////// Access functions ////////////////////////////
static G4PhysicsTable* GetAngleDistrTable() { return fAngleDistrTable ; } ;
static G4PhysicsTable* GetEnergyDistrTable() { return fEnergyDistrTable ; } ;
static G4int GetSympsonNumber() { return fSympsonNumber ; } ;
static G4int GetBinTR() { return fBinTR ; } ;
static G4double GetMinProtonTkin() { return fMinProtonTkin ; } ;
static G4double GetMaxProtonTkin() { return fMaxProtonTkin ; } ;
static G4int GetTotBin() { return fTotBin ; } ;
protected :
private : /////////////// Data members ///////////////////////////
G4Gamma* fPtrGamma ; // pointer to TR photon
G4double* fGammaCutInKineticEnergy ; // TR photon cut in energy array
G4double fGammaTkinCut ; // Tkin cut of TR photon in current mat.
static G4PhysicsTable* fAngleDistrTable ;
static G4PhysicsTable* fEnergyDistrTable ;
static G4int fSympsonNumber ; // Accuracy of Sympson integration
static G4double fTheMinEnergyTR ; // static min TR energy
static G4double fTheMaxEnergyTR ; // static max TR energy
G4double fMinEnergyTR ; // min TR energy in material
G4double fMaxEnergyTR ; // max TR energy in material
static G4double fTheMaxAngle ; // max theta of TR quanta
static G4double fTheMinAngle ; // max theta of TR quanta
G4double fMaxThetaTR ; // max theta of TR quanta
static G4int fBinTR ; // number of bins in TR vectors
static G4double fMinProtonTkin ; // min Tkin of proton in tables
static G4double fMaxProtonTkin ; // max Tkin of proton in tables
static G4int fTotBin ; // number of bins in log scale
G4double fGamma ; // current Lorentz factor
static G4double fPlasmaCof ; // physical consts for plasma energy
static G4double fCofTR ;
G4double fSigma1 ; // plasma energy Sq of matter1
G4double fSigma2 ; // plasma energy Sq of matter2
} ; // end of G4ForwardXrayTR class ---------------------------
#endif // G4FORWARDXRAYTR_H
@@ -0,0 +1,207 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4Scintillation.hh,v 2.1 1998/11/10 01:06:55 gum Exp $
// GEANT4 tag $Name: geant4-00 $
//
//
////////////////////////////////////////////////////////////////////////
// Scintillation Light Class Definition
////////////////////////////////////////////////////////////////////////
//
// File: G4Scintillation.hh
// Description: Discrete Process - Generation of Scintillation Photons
// Version: 1.0
// Created: 1998-11-07
// Author: Peter Gumplinger
// Updated:
//
// mail: gum@triumf.ca
//
////////////////////////////////////////////////////////////////////////
#ifndef G4Scintillation_h
#define G4Scintillation_h 1
/////////////
// Includes
/////////////
#include "globals.hh"
#include "templates.hh"
#include "Randomize.hh"
#include "G4ThreeVector.hh"
#include "G4ParticleMomentum.hh"
#include "G4Step.hh"
#include "G4VDiscreteProcess.hh"
#include "G4OpticalPhoton.hh"
#include "G4DynamicParticle.hh"
#include "G4Material.hh"
#include "G4PhysicsTable.hh"
#include "G4MaterialPropertiesTable.hh"
#include "G4PhysicsOrderedFreeVector.hh"
/////////////////////
// Class Definition
/////////////////////
class G4Scintillation : public G4VDiscreteProcess
{
private:
//////////////
// Operators
//////////////
// G4Scintillation& operator=(const G4Scintillation &right);
public:
////////////////////////////////
// Constructors and Destructor
////////////////////////////////
G4Scintillation(const G4String& processName = "Scintillation");
// G4Scintillation(const G4Scintillation &right);
~G4Scintillation();
////////////
// Methods
////////////
G4bool IsApplicable(const G4ParticleDefinition& aParticleType);
G4double GetMeanFreePath(const G4Track& aTrack,
G4double ,
G4ForceCondition* );
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep);
void SetTrackSecondariesFirst(const G4bool state);
G4bool GetTrackSecondariesFirst() const;
void SetScintillationYield(const G4double yield);
G4double GetScintillationYield() const;
void SetResolutionScale(const G4double scale);
G4double GetResolutionScale() const;
void SetScintillationTime(const G4double time);
G4double GetScintillationTime() const;
G4PhysicsTable* GetPhysicsTable() const;
// Returns the address of the physics table.
void DumpPhysicsTable() const;
private:
void BuildThePhysicsTable();
///////////////////////
// Class Data Members
///////////////////////
protected:
G4PhysicsTable* thePhysicsTable;
// A Physics Table can be either a cross-sections table or
// an energy table (or can be used for other specific
// purposes).
private:
G4bool fTrackSecondariesFirst;
G4double ScintillationYield;
G4double ScintillationTime;
G4double ResolutionScale;
};
////////////////////
// Inline methods
////////////////////
inline
G4bool G4Scintillation::IsApplicable(const G4ParticleDefinition& aParticleType)
{
return true;
}
inline
void G4Scintillation::SetTrackSecondariesFirst(const G4bool state)
{
fTrackSecondariesFirst = state;
}
inline
G4bool G4Scintillation::GetTrackSecondariesFirst() const
{
return fTrackSecondariesFirst;
}
inline
void G4Scintillation::SetScintillationYield(const G4double yield)
{
ScintillationYield = yield;
}
inline
G4double G4Scintillation::GetScintillationYield() const
{
return ScintillationYield;
}
inline
void G4Scintillation::SetResolutionScale(const G4double scale)
{
ResolutionScale = scale;
}
inline
G4double G4Scintillation::GetResolutionScale() const
{
return ResolutionScale;
}
inline
void G4Scintillation::SetScintillationTime(const G4double time)
{
ScintillationTime = time;
}
inline
G4double G4Scintillation::GetScintillationTime() const
{
return ScintillationTime;
}
inline
G4PhysicsTable* G4Scintillation::GetPhysicsTable() const
{
return thePhysicsTable;
}
inline
void G4Scintillation::DumpPhysicsTable() const
{
G4int PhysicsTableSize = thePhysicsTable->entries();
G4PhysicsOrderedFreeVector *v;
for (G4int i = 0 ; i < PhysicsTableSize ; i++ )
{
v = (G4PhysicsOrderedFreeVector*)(*thePhysicsTable)[i];
v->DumpValues();
}
}
#endif /* G4Scintillation_h */
@@ -0,0 +1,129 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4TransitionRadiation.hh,v 2.1 1998/11/27 13:35:12 grichine Exp $
// GEANT4 tag $Name: geant4-00 $
//
// G4TransitionRadiation -- header file
//
// Class for description of transition radiation generated
// by charged particle crossed interface between material 1
// and material 2 (1 -> 2). Transition radiation could be of kind:
// - optical back
// - optical forward
// - X-ray forward (for relativistic case Tkin/mass >= 10^2)
//
// GEANT 4 class header file --- Copyright CERN 1995
// CERB Geneva Switzerland
//
// for information related to this code, please, contact
// CERN, CN Division, ASD Group
// History:
// 18.12.97, V. Grichine (Vladimir.Grichine@cern.ch)
#ifndef G4TransitionRadiation_h
#define G4TransitionRadiation_h
#include "G4VDiscreteProcess.hh"
#include "G4Material.hh"
class G4TransitionRadiation : public G4VDiscreteProcess
{
public:
// Constructors
G4TransitionRadiation( const G4String& processName = "TR") ;
// G4TransitionRadiation(const G4TransitionRadiation& right) ;
// Destructor
~G4TransitionRadiation() ;
// Operators
// G4TransitionRadiation& operator=(const G4TransitionRadiation& right) ;
// G4int operator==(const G4TransitionRadiation& right)const ;
// G4int operator!=(const G4TransitionRadiation& right)const ;
// Methods
G4bool IsApplicable(const G4ParticleDefinition& aParticleType)
{
return ( aParticleType.GetPDGCharge() != 0.0 );
}
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
G4ForceCondition* condition)
{
*condition = Forced;
return DBL_MAX; // so TR doesn't limit mean free path
}
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
ClearNumberOfInteractionLengthLeft();
return &aParticleChange;
}
virtual
G4double SpectralAngleTRdensity( G4double energy,
G4double varAngle ) const = 0 ;
G4double IntegralOverEnergy( G4double energy1,
G4double energy2,
G4double varAngle ) const ;
G4double IntegralOverAngle( G4double energy,
G4double varAngle1,
G4double varAngle2 ) const ;
G4double AngleIntegralDistribution( G4double varAngle1,
G4double varAngle2 ) const ;
G4double EnergyIntegralDistribution( G4double energy1,
G4double energy2 ) const ;
// Access functions
protected :
G4int fMatIndex1 ; // index of the 1st material
G4int fMatIndex2 ; // index of the 2nd material
private :
G4double fGamma ;
// Local constants
static const G4int fSympsonNumber ; // Accuracy of Sympson integration 10
static const G4int fGammaNumber ; // = 15
static const G4int fPointNumber ; // = 100
G4double fMinEnergy ; // min TR energy
G4double fMaxEnergy ; // max TR energy
G4double fMaxTheta ; // max theta of TR quanta
G4double fSigma1 ; // plasma energy Sq of matter1
G4double fSigma2 ; // plasma energy Sq of matter2
} ;
#endif // G4TransitionRadiation_h
@@ -0,0 +1,500 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4Cerenkov.cc,v 2.4 1998/08/25 22:06:03 gum Exp $
// GEANT4 tag $Name: geant4-00 $
//
////////////////////////////////////////////////////////////////////////
// Cerenkov Radiation Class Implementation
////////////////////////////////////////////////////////////////////////
//
// File: G4Cerenkov.cc
// Description: Continuous Process -- Generation of Cerenkov Photons
// Version: 2.1
// Created: 1996-02-21
// Author: Juliet Armstrong
// Updated: 1997-08-08 by Peter Gumplinger
// > add protection against /0
// > G4MaterialPropertiesTable; new physics/tracking scheme
// mail: gum@triumf.ca
//
////////////////////////////////////////////////////////////////////////
#include "G4ios.hh"
#include "G4Cerenkov.hh"
/////////////////////////
// Class Implementation
/////////////////////////
//////////////
// Operators
//////////////
// G4Cerenkov::operator=(const G4Cerenkov &right)
// {
// }
/////////////////
// Constructors
/////////////////
G4Cerenkov::G4Cerenkov(const G4String& processName)
: G4VContinuousProcess(processName)
{
fTrackSecondariesFirst = false;
fMaxPhotons = 0;
thePhysicsTable = NULL;
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created " << endl;
}
BuildThePhysicsTable();
}
// G4Cerenkov::G4Cerenkov(const G4Cerenkov &right)
// {
// }
////////////////
// Destructors
////////////////
G4Cerenkov::~G4Cerenkov()
{
if (thePhysicsTable!= NULL) {
thePhysicsTable->clearAndDestroy();
delete thePhysicsTable;
}
}
////////////
// Methods
////////////
// AlongStepDoIt
// -------------
//
G4VParticleChange*
G4Cerenkov::AlongStepDoIt(const G4Track& aTrack, const G4Step& aStep)
// This routine is called for each tracking Step of a charged particle
// in a radiator. A Poisson-distributed number of photons is generated
// according to the Cerenkov formula, distributed evenly along the track
// segment and uniformly azimuth w.r.t. the particle direction. The
// parameters are then transformed into the Master Reference System, and
// they are added to the particle change.
{
//////////////////////////////////////////////////////
// Should we ensure that the material is dispersive?
//////////////////////////////////////////////////////
aParticleChange.Initialize(aTrack);
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
const G4Material* aMaterial = aTrack.GetMaterial();
G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
G4ThreeVector x0 = pPreStepPoint->GetPosition();
G4ThreeVector p0 = pPreStepPoint->GetMomentumDirection();
G4double t0 = pPreStepPoint->GetGlobalTime();
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
if (!aMaterialPropertiesTable)
return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
const G4MaterialPropertyVector* Rindex =
aMaterialPropertiesTable->GetProperty("RINDEX");
if (!Rindex)
return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
G4double MeanNumPhotons =
GetAverageNumberOfPhotons(aParticle,aMaterial,Rindex);
G4double step_length;
step_length = aStep.GetStepLength();
if(step_length == 0.0)step_length = aStep.GetStepLength();
MeanNumPhotons = MeanNumPhotons * step_length;
// RandPoisson is a utility class. It provides functions
// that act on HepRandom
G4int NumPhotons = (G4int) RandPoisson::shoot(MeanNumPhotons);
if (NumPhotons == 0) {
// return unchanged particle and no secondaries
aParticleChange.SetNumberOfSecondaries(0);
return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
}
////////////////////////////////////////////////////////////////
aParticleChange.SetNumberOfSecondaries(NumPhotons);
if (fTrackSecondariesFirst)
aParticleChange.SetStatusChange(fSuspend);
////////////////////////////////////////////////////////////////
G4double Pmin = Rindex->GetMinPhotonMomentum();
G4double Pmax = Rindex->GetMaxPhotonMomentum();
G4double dp = Pmax - Pmin;
G4double nMax = Rindex->GetMaxProperty();
G4double BetaInverse = aParticle->GetTotalEnergy() /
aParticle->GetTotalMomentum();
G4double maxCos = BetaInverse / nMax;
G4double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
for (G4int i = 0; i < NumPhotons; i++) {
// Determine photon momentum
G4double rand;
G4double sampledMomentum, sampledRI;
G4double cosTheta, sin2Theta;
// sample a momentum
do {
rand = G4UniformRand();
sampledMomentum = Pmin + rand * dp;
sampledRI = Rindex->GetProperty(sampledMomentum);
cosTheta = BetaInverse / sampledRI;
sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
rand = G4UniformRand();
} while (rand*maxSin2 > sin2Theta);
// Generate random position of photon on cone surface
// defined by Theta
rand = G4UniformRand();
G4double phi = 2*M_PI*rand;
G4double sinPhi = sin(phi);
G4double cosPhi = cos(phi);
// calculate x,y, and z components of photon momentum
// (in coord system with primary particle direction
// aligned with the z axis)
G4double sinTheta = sqrt(sin2Theta);
G4double px = sinTheta*cosPhi;
G4double py = sinTheta*sinPhi;
G4double pz = cosTheta;
// Create photon momentum direction vector
// The momentum direction is still with respect
// to the coordinate system where the primary
// particle direction is aligned with the z axis
G4ParticleMomentum photonMomentum(px, py, pz);
// Rotate momentum direction back to global reference
// system
photonMomentum.rotateUz(p0);
// Determine polarization of new photon
G4double sx = cosTheta*cosPhi;
G4double sy = cosTheta*sinPhi;
G4double sz = -sinTheta;
G4ThreeVector photonPolarization(sx, sy, sz);
// Rotate back to original coord system
photonPolarization.rotateUz(p0);
// Generate a new photon:
G4DynamicParticle* aCerenkovPhoton =
new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(),
photonMomentum);
aCerenkovPhoton->SetPolarization
(photonPolarization.x(),
photonPolarization.y(),
photonPolarization.z());
aCerenkovPhoton->SetKineticEnergy(sampledMomentum);
// Generate new G4Track object:
rand = G4UniformRand();
G4double delta = rand * aStep.GetStepLength();
G4ThreeVector aSecondaryPosition = x0 + delta * p0;
G4double deltaTime = delta /
((pPreStepPoint->GetVelocity()+
pPostStepPoint->GetVelocity())/2.);
G4double aSecondaryTime = t0 + deltaTime;
G4Track* aSecondaryTrack =
new G4Track(aCerenkovPhoton,aSecondaryTime,aSecondaryPosition);
aSecondaryTrack->SetTouchable(pPreStepPoint->
GetTouchable());
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
aParticleChange.AddSecondary(aSecondaryTrack);
}
if (verboseLevel>0) {
G4cout << "\n Exiting from G4Cerenkov::DoIt -- NumberOfSecondaries = "
<< aParticleChange.GetNumberOfSecondaries() << endl;
}
return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
}
// BuildThePhysicsTable for the Cerenkov process
// ---------------------------------------------
//
void G4Cerenkov::BuildThePhysicsTable()
{
if (thePhysicsTable) return;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
// create new physics table
thePhysicsTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int i=0 ; i < numOfMaterials; i++)
{
G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
// Retrieve vector of refraction indices for the material
// from the material's optical properties table
G4Material* aMaterial = (*theMaterialTable)(i);
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
if (aMaterialPropertiesTable) {
G4MaterialPropertyVector* theRefractionIndexVector =
aMaterialPropertiesTable->GetProperty("RINDEX");
if (theRefractionIndexVector) {
// Retrieve the first refraction index in vector
// of (photon momentum, refraction index) pairs
theRefractionIndexVector->ResetIterator();
++(*theRefractionIndexVector); // advance to 1st entry
G4double currentRI = theRefractionIndexVector->
GetProperty();
if (currentRI > 1.0) {
// Create first (photon momentum, Cerenkov Integral)
// pair
G4double currentPM = theRefractionIndexVector->
GetPhotonMomentum();
G4double currentCAI = 0.0;
aPhysicsOrderedFreeVector->
InsertValues(currentPM , currentCAI);
// Set previous values to current ones prior to loop
G4double prevPM = currentPM;
G4double prevCAI = currentCAI;
G4double prevRI = currentRI;
// loop over all (photon momentum, refraction index)
// pairs stored for this material
while(++(*theRefractionIndexVector))
{
currentRI=theRefractionIndexVector->
GetProperty();
currentPM = theRefractionIndexVector->
GetPhotonMomentum();
currentCAI = 0.5*(1.0/(prevRI*prevRI) +
1.0/(currentRI*currentRI));
currentCAI = prevCAI +
(currentPM - prevPM) * currentCAI;
aPhysicsOrderedFreeVector->
InsertValues(currentPM, currentCAI);
prevPM = currentPM;
prevCAI = currentCAI;
prevRI = currentRI;
}
}
}
}
// The Cerenkov integral for a given material
// will be inserted in thePhysicsTable
// according to the position of the material in
// the material table.
thePhysicsTable->insertAt(i,aPhysicsOrderedFreeVector);
}
}
// GetContinuousStepLimit
// ----------------------
//
G4double
G4Cerenkov::GetContinuousStepLimit(const G4Track& aTrack,
G4double ,
G4double ,
G4double& )
{
// If user has defined an average maximum number of photons to
// be generated in a Step, then return the Step length for that
// number of photons.
if (fMaxPhotons == 0) return DBL_MAX;
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
const G4Material* aMaterial = aTrack.GetMaterial();
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
if (!aMaterialPropertiesTable) return DBL_MAX;
const G4MaterialPropertyVector* Rindex =
aMaterialPropertiesTable->GetProperty("RINDEX");
if (!Rindex) return DBL_MAX;
G4double MeanNumPhotons =
GetAverageNumberOfPhotons(aParticle,aMaterial,Rindex);
if(MeanNumPhotons == 0.0) return DBL_MAX;
G4double StepLimit = fMaxPhotons / MeanNumPhotons;
return StepLimit;
}
// GetAverageNumberOfPhotons
// -------------------------
// This routine computes the number of Cerenkov photons produced per
// GEANT-unit (millimeter) in the current medium.
// ^^^^^^^^^^
G4double
G4Cerenkov::GetAverageNumberOfPhotons(const G4DynamicParticle* aParticle,
const G4Material* aMaterial,
const G4MaterialPropertyVector* Rindex) const
{
const G4double Rfact = 369.81/(eV * cm);
if(aParticle->GetTotalMomentum() == 0.0)return 0.0;
G4double BetaInverse = aParticle->GetTotalEnergy() /
aParticle->GetTotalMomentum();
// Vectors used in computation of Cerenkov Angle Integral:
// - Refraction Indices for the current material
// - new G4PhysicsOrderedFreeVector allocated to hold CAI's
G4int materialIndex = G4Material::GetMaterialTable()->index(aMaterial);
// Retrieve the Cerenkov Angle Integrals for this material
G4PhysicsOrderedFreeVector* CerenkovAngleIntegrals =
(G4PhysicsOrderedFreeVector*)((*thePhysicsTable)(materialIndex));
// Min and Max photon momenta
G4double Pmin = Rindex->GetMinPhotonMomentum();
G4double Pmax = Rindex->GetMaxPhotonMomentum();
// Min and Max Refraction Indices
G4double nMin = Rindex->GetMinProperty();
G4double nMax = Rindex->GetMaxProperty();
// Max Cerenkov Angle Integral
G4double CAImax = CerenkovAngleIntegrals->GetMaxValue();
G4double dp, ge;
// If n(Pmax) < 1/Beta -- no photons generated
if (nMax < BetaInverse) {
dp = 0;
ge = 0;
}
// otherwise if n(Pmin) >= 1/Beta -- photons generated
else if (nMin > BetaInverse) {
dp = Pmax - Pmin;
ge = CAImax;
}
// If n(Pmin) < 1/Beta, and n(Pmax) >= 1/Beta, then
// we need to find a P such that the value of n(P) == 1/Beta.
// Interpolation is performed by the GetPhotonMomentum() and
// GetProperty() methods of the G4MaterialPropertiesTable and
// the GetValue() method of G4PhysicsVector.
else {
Pmin = Rindex->GetPhotonMomentum(BetaInverse);
dp = Pmax - Pmin;
// need boolean for current implementation of G4PhysicsVector
// ==> being phased out
G4bool isOutRange;
G4double CAImin = CerenkovAngleIntegrals->
GetValue(Pmin, isOutRange);
ge = CAImax - CAImin;
if (verboseLevel>0) {
G4cout << "CAImin = " << CAImin << endl;
G4cout << "ge = " << ge << endl;
}
}
// particle charge
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
// Calculate number of photons
G4double NumPhotons =
Rfact * charge*charge * (dp - ge * BetaInverse*BetaInverse);
return NumPhotons / cm;
}
@@ -0,0 +1,786 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4ForwardXrayTR.cc,v 2.3 1998/11/27 13:37:15 grichine Exp $
// GEANT4 tag $Name: geant4-00 $
//
// G4ForwardXrayTR class -- implementation file
// GEANT 4 class implementation file --- Copyright CERN 1995
// CERN Geneva Switzerland
// For information related to this code, please, contact
// CERN, CN Division, ASD Group
// History:
// 1st version 11.09.97 V. Grichine (Vladimir.Grichine@cern.ch )
// 2nd version 17.12.97 V. Grichine
#include <math.h>
// #include "G4ios.hh"
// #include <fstream.h>
// #include <stdlib.h>
#include "G4ForwardXrayTR.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "globals.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
#include "G4PhysicsLinearVector.hh"
#include "G4PhysicsLogVector.hh"
// Table initialization
G4PhysicsTable* G4ForwardXrayTR::fAngleDistrTable = NULL ;
G4PhysicsTable* G4ForwardXrayTR::fEnergyDistrTable = NULL ;
// Initialization of local constants
G4int G4ForwardXrayTR::fSympsonNumber = 100 ;
G4double G4ForwardXrayTR::fTheMinEnergyTR = 1.0*keV ;
G4double G4ForwardXrayTR::fTheMaxEnergyTR = 100.0*keV ;
G4double G4ForwardXrayTR::fTheMaxAngle = 1.0e-3 ;
G4double G4ForwardXrayTR::fTheMinAngle = 5.0e-6 ;
G4int G4ForwardXrayTR::fBinTR = 50 ;
G4double G4ForwardXrayTR::fMinProtonTkin = 100.0*GeV ;
G4double G4ForwardXrayTR::fMaxProtonTkin = 100.0*TeV ;
G4int G4ForwardXrayTR::fTotBin = 50 ;
G4double G4ForwardXrayTR::fPlasmaCof = 4.0*pi*fine_structure_const*
hbarc*hbarc*hbarc/electron_mass_c2 ;
G4double G4ForwardXrayTR::fCofTR = fine_structure_const/pi ;
///////////////////////////////////////////////////////////////////////
//
// Constructor for preparation tables with angle and energy TR distributions
// in all materials involved in test program. Lorentz factors correspond to
// kinetic energies of protons between 100*GeV and 100*TeV, ~ 10^2-10^5
//
// Recommended only for use in applications with
// few light materials involved !!!!!!!!!!!!!!
G4ForwardXrayTR::G4ForwardXrayTR()
: G4TransitionRadiation("XrayTR")
{
G4int iMat, jMat, iTkin, iTR, iPlace ;
static
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4int numOfMat = theMaterialTable->length() ;
fGammaCutInKineticEnergy = fPtrGamma->GetCutsInEnergy() ;
fMatIndex1 = -1 ;
fMatIndex2 = -1 ;
fAngleDistrTable = new G4PhysicsTable(numOfMat*(numOfMat - 1)*fTotBin) ;
fEnergyDistrTable = new G4PhysicsTable(numOfMat*(numOfMat - 1)*fTotBin) ;
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(fMinProtonTkin,
fMaxProtonTkin,
fTotBin ) ;
for(iMat=0;iMat<numOfMat;iMat++) // loop over pairs of different materials
{
for(jMat=0;jMat<numOfMat;jMat++) // transition iMat -> jMat !!!
{
if(iMat == jMat) continue ; // no TR !!
else
{
const G4Material* mat1 = (*theMaterialTable)[iMat] ;
const G4Material* mat2 = (*theMaterialTable)[jMat] ;
fSigma1 = fPlasmaCof*(mat1->GetElectronDensity()) ;
fSigma2 = fPlasmaCof*(mat2->GetElectronDensity()) ;
fGammaTkinCut = fGammaCutInKineticEnergy[jMat] ; // TR photon in jMat !
if(fGammaTkinCut > fTheMinEnergyTR) // setting of min/max TR energies
{
fMinEnergyTR = fGammaTkinCut ;
}
else
{
fMinEnergyTR = fTheMinEnergyTR ;
}
if(fGammaTkinCut > fTheMaxEnergyTR)
{
fMaxEnergyTR = 2.0*fGammaTkinCut ; // usually very low TR rate
}
else
{
fMaxEnergyTR = fTheMaxEnergyTR ;
}
for(iTkin=0;iTkin<fTotBin;iTkin++) // Lorentz factor loop
{
G4PhysicsLogVector*
energyVector = new G4PhysicsLogVector(fMinEnergyTR,
fMaxEnergyTR,
fBinTR ) ;
G4PhysicsLinearVector*
angleVector = new G4PhysicsLinearVector( 0.0,
fMaxThetaTR,
fBinTR ) ;
G4double energySum = 0.0 ;
G4double angleSum = 0.0 ;
fGamma = 1.0 + (aVector->GetLowEdgeEnergy(iTkin)/proton_mass_c2) ;
fMaxThetaTR = 10000.0/(fGamma*fGamma) ;
if(fMaxThetaTR > fTheMaxAngle)
{
fMaxThetaTR = fTheMaxAngle ;
}
else
{
if(fMaxThetaTR < fTheMinAngle)
{
fMaxThetaTR = fTheMinAngle ;
}
}
energyVector->PutValue(fBinTR-1,energySum) ;
angleVector->PutValue(fBinTR-1,angleSum) ;
for(iTR=fBinTR-2;iTR>=0;iTR--)
{
energySum += fCofTR*EnergySum(energyVector->GetLowEdgeEnergy(iTR),
energyVector->GetLowEdgeEnergy(iTR+1)) ;
angleSum += fCofTR*AngleSum(angleVector->GetLowEdgeEnergy(iTR),
angleVector->GetLowEdgeEnergy(iTR+1)) ;
energyVector->PutValue(iTR,energySum) ;
angleVector->PutValue(iTR,angleSum) ;
}
if(jMat < iMat)
{
iPlace = (iMat*(numOfMat-1)+jMat)*fTotBin+iTkin ;
}
else // jMat > iMat right part of matrices (jMat-1) !
{
iPlace = (iMat*(numOfMat-1)+jMat-1)*fTotBin+iTkin ;
}
fEnergyDistrTable->insertAt(iPlace,energyVector) ;
fAngleDistrTable->insertAt(iPlace,angleVector) ;
} // iTkin
} // jMat != iMat
} // jMat
} // iMat
}
//////////////////////////////////////////////////////////////////////
//
// Constructor for creation of physics tables (angle and energy TR
// distributions) for a couple of selected materials.
//
// Recommended for use in applications with many materials involved,
// when only few (usually couple) materials are interested for generation
// of TR on the interface between them
G4ForwardXrayTR::G4ForwardXrayTR( G4Material* pMat1,
G4Material* pMat2,
const G4String& processName )
: G4TransitionRadiation(processName)
{
G4int iMat, jMat, iTkin, iTR, iPlace ;
static
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4int numOfMat = theMaterialTable->length() ;
fGammaCutInKineticEnergy = fPtrGamma->GetCutsInEnergy() ;
fMatIndex1 = pMat1->GetIndex() ;
fMatIndex2 = pMat2->GetIndex() ;
fAngleDistrTable = new G4PhysicsTable(numOfMat*(numOfMat - 1)*fTotBin) ;
fEnergyDistrTable = new G4PhysicsTable(numOfMat*(numOfMat - 1)*fTotBin) ;
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(fMinProtonTkin,
fMaxProtonTkin,
fTotBin ) ;
for(iMat=0;iMat<numOfMat;iMat++) // loop over pairs of different materials
{
if( iMat != fMatIndex1 && iMat != fMatIndex2 ) continue ;
for(jMat=0;jMat<numOfMat;jMat++) // transition iMat -> jMat !!!
{
if( iMat == jMat || ( jMat != fMatIndex1 && jMat != fMatIndex2 ) )
{
continue ;
}
else
{
const G4Material* mat1 = (*theMaterialTable)[iMat] ;
const G4Material* mat2 = (*theMaterialTable)[jMat] ;
fSigma1 = fPlasmaCof*(mat1->GetElectronDensity()) ;
fSigma2 = fPlasmaCof*(mat2->GetElectronDensity()) ;
fGammaTkinCut = fGammaCutInKineticEnergy[jMat] ; // TR photon in jMat !
if(fGammaTkinCut > fTheMinEnergyTR) // setting of min/max TR energies
{
fMinEnergyTR = fGammaTkinCut ;
}
else
{
fMinEnergyTR = fTheMinEnergyTR ;
}
if(fGammaTkinCut > fTheMaxEnergyTR)
{
fMaxEnergyTR = 2.0*fGammaTkinCut ; // usually very low TR rate
}
else
{
fMaxEnergyTR = fTheMaxEnergyTR ;
}
for(iTkin=0;iTkin<fTotBin;iTkin++) // Lorentz factor loop
{
G4PhysicsLogVector*
energyVector = new G4PhysicsLogVector(fMinEnergyTR,
fMaxEnergyTR,
fBinTR ) ;
G4PhysicsLinearVector*
angleVector = new G4PhysicsLinearVector( 0.0,
fMaxThetaTR,
fBinTR ) ;
G4double energySum = 0.0 ;
G4double angleSum = 0.0 ;
fGamma = 1.0 + (aVector->GetLowEdgeEnergy(iTkin)/proton_mass_c2) ;
fMaxThetaTR = 10000.0/(fGamma*fGamma) ;
if(fMaxThetaTR > fTheMaxAngle)
{
fMaxThetaTR = fTheMaxAngle ;
}
else
{
if(fMaxThetaTR < fTheMinAngle)
{
fMaxThetaTR = fTheMinAngle ;
}
}
energyVector->PutValue(fBinTR-1,energySum) ;
angleVector->PutValue(fBinTR-1,angleSum) ;
for(iTR=fBinTR-2;iTR>=0;iTR--)
{
energySum += fCofTR*EnergySum(energyVector->GetLowEdgeEnergy(iTR),
energyVector->GetLowEdgeEnergy(iTR+1)) ;
angleSum += fCofTR*AngleSum(angleVector->GetLowEdgeEnergy(iTR),
angleVector->GetLowEdgeEnergy(iTR+1)) ;
energyVector->PutValue(iTR,energySum) ;
angleVector->PutValue(iTR,angleSum) ;
}
if(jMat < iMat)
{
iPlace = (iMat*(numOfMat-1)+jMat)*fTotBin+iTkin ;
}
else // jMat > iMat right part of matrices (jMat-1) !
{
iPlace = (iMat*(numOfMat-1)+jMat-1)*fTotBin+iTkin ;
}
fEnergyDistrTable->insertAt(iPlace,energyVector) ;
fAngleDistrTable->insertAt(iPlace,angleVector) ;
} // iTkin
} // jMat != iMat
} // jMat
} // iMat
}
//////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4ForwardXrayTR::~G4ForwardXrayTR()
{
;
}
///////////////////////////////////////////////////////////////////////
//
// This function returns the spectral and angle density of TR quanta
// in X-ray energy region generated forward when a relativistic
// charged particle crosses interface between two materials.
// The high energy small theta approximation is applied.
// (matter1 -> matter2)
// varAngle =2* (1 - cos(Theta)) or approximately = Theta*Theta
//
G4double
G4ForwardXrayTR::SpectralAngleTRdensity( G4double energy,
G4double varAngle ) const
{
G4double formationLength1, formationLength2 ;
formationLength1 = 1.0/
(1.0/(fGamma*fGamma)
+ fSigma1/(energy*energy)
+ varAngle) ;
formationLength2 = 1.0/
(1.0/(fGamma*fGamma)
+ fSigma2/(energy*energy)
+ varAngle) ;
return (varAngle/energy)*(formationLength1 - formationLength2)
*(formationLength1 - formationLength2) ;
}
//////////////////////////////////////////////////////////////////
//
// Analytical formula for angular density of X-ray TR photons
//
G4double G4ForwardXrayTR::AngleDensity( G4double energy,
G4double varAngle ) const
{
G4double x, x2, a, b, c, d, f, a2, b2, a4, b4 ;
G4double cof1, cof2, cof3 ;
x = 1.0/energy ;
x2 = x*x ;
c = 1.0/fSigma1 ;
d = 1.0/fSigma2 ;
f = (varAngle + 1.0/(fGamma*fGamma)) ;
a2 = c*f ;
b2 = d*f ;
a4 = a2*a2 ;
b4 = b2*b2 ;
a = sqrt(a2) ;
b = sqrt(b2) ;
cof1 = c*c*(0.5/(a2*(x2 +a2)) +0.5*log(x2/(x2 +a2))/a4) ;
cof3 = d*d*(0.5/(b2*(x2 +b2)) +0.5*log(x2/(x2 +b2))/b4) ;
cof2 = -c*d*(log(x2/(x2 +b2))/b2 - log(x2/(x2 +a2))/a2)/(a2 - b2) ;
return -varAngle*(cof1 + cof2 + cof3) ;
}
/////////////////////////////////////////////////////////////////////
//
// Definite integral of X-ray TR spectral-angle density from energy1
// to energy2
//
G4double G4ForwardXrayTR::EnergyInterval( G4double energy1,
G4double energy2,
G4double varAngle ) const
{
return AngleDensity(energy2,varAngle)
- AngleDensity(energy1,varAngle) ;
}
//////////////////////////////////////////////////////////////////////
//
// Integral angle distribution of X-ray TR photons based on analytical
// formula for angle density
//
G4double G4ForwardXrayTR::AngleSum( G4double varAngle1,
G4double varAngle2 ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += EnergyInterval(fMinEnergyTR,fMaxEnergyTR,varAngle1 + 2*i*h ) ;
sumOdd += EnergyInterval(fMinEnergyTR,fMaxEnergyTR,
varAngle1 + (2*i - 1)*h ) ;
}
sumOdd += EnergyInterval(fMinEnergyTR,fMaxEnergyTR,
varAngle1 + (2*fSympsonNumber - 1)*h ) ;
return h*(EnergyInterval(fMinEnergyTR,fMaxEnergyTR,varAngle1)
+ EnergyInterval(fMinEnergyTR,fMaxEnergyTR,varAngle2)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
/////////////////////////////////////////////////////////////////////
//
// Analytical Expression for spectral density of Xray TR photons
// x = 2*(1 - cos(Theta)) ~ Theta^2
//
G4double G4ForwardXrayTR::SpectralDensity( G4double energy,
G4double x ) const
{
G4double a, b ;
a = 1.0/(fGamma*fGamma)
+ fSigma1/(energy*energy) ;
b = 1.0/(fGamma*fGamma)
+ fSigma2/(energy*energy) ;
return ( (a + b)*log((x + b)/(x + a))/(a - b)
+ a/(x + a) + b/(x + b) )/energy ;
}
////////////////////////////////////////////////////////////////////
//
// The spectral density in some angle interval from varAngle1 to
// varAngle2
//
G4double G4ForwardXrayTR::AngleInterval( G4double energy,
G4double varAngle1,
G4double varAngle2 ) const
{
return SpectralDensity(energy,varAngle2)
- SpectralDensity(energy,varAngle1) ;
}
////////////////////////////////////////////////////////////////////
//
// Integral spectral distribution of X-ray TR photons based on
// analytical formula for spectral density
//
G4double G4ForwardXrayTR::EnergySum( G4double energy1,
G4double energy2 ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(energy2 - energy1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += AngleInterval(energy1 + 2*i*h,0.0,fMaxThetaTR);
sumOdd += AngleInterval(energy1 + (2*i - 1)*h,0.0,fMaxThetaTR) ;
}
sumOdd += AngleInterval(energy1 + (2*fSympsonNumber - 1)*h,
0.0,fMaxThetaTR) ;
return h*( AngleInterval(energy1,0.0,fMaxThetaTR)
+ AngleInterval(energy2,0.0,fMaxThetaTR)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
/////////////////////////////////////////////////////////////////////////
//
// PostStepDoIt function for creation of forward X-ray photons in TR process
// on boubndary between two materials with really different plasma energies
//
G4VParticleChange* G4ForwardXrayTR::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
aParticleChange.Initialize(aTrack);
G4int iMat, jMat, iTkin, iPlace, numOfMat, numOfTR, iTR, iTransfer ;
G4double energyPos, anglePos, energyTR, theta, phi, dirX, dirY, dirZ ;
G4double W, W1, W2, E1, E2 ;
static
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
numOfMat = theMaterialTable->length() ;
G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
if (pPostStepPoint->GetStepStatus() != fGeomBoundary)
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
if (aTrack.GetStepLength()<=kCarTolerance/2)
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
// Come on boundary, so begin to try TR
iMat = pPreStepPoint ->GetPhysicalVolume()->
GetLogicalVolume()->GetMaterial()->GetIndex() ;
jMat = pPostStepPoint->GetPhysicalVolume()->
GetLogicalVolume()->GetMaterial()->GetIndex() ;
// The case of equal or approximate (in terms of plasma energy) materials
// No TR photons ?!
if ( iMat == jMat
|| ( (fMatIndex1 >= 0 && fMatIndex1 >= 0)
&& ( iMat != fMatIndex1 && iMat != fMatIndex2 )
&& ( jMat != fMatIndex1 && jMat != fMatIndex2 ) )
|| (*theMaterialTable)(iMat)->GetState() ==
(*theMaterialTable)(jMat)->GetState()
||( (*theMaterialTable)(iMat)->GetState() == kStateSolid
&& (*theMaterialTable)(jMat)->GetState() == kStateLiquid )
||( (*theMaterialTable)(iMat)->GetState() == kStateLiquid
&& (*theMaterialTable)(jMat)->GetState() == kStateSolid ) )
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep) ;
}
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
if(charge == 0.0) // Uncharged particle doesn't Generate TR photons
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
// Now we are ready to Generate TR photons
G4double chargeSq = charge*charge ;
G4double kinEnergy = aParticle->GetKineticEnergy() ;
G4double massRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass() ;
G4double TkinScaled = kinEnergy*massRatio ;
G4PhysicsLogVector*
aLogVector = new G4PhysicsLogVector(fMinProtonTkin,fMaxProtonTkin,fTotBin) ;
for(iTkin=0;iTkin<fTotBin;iTkin++)
{
if(TkinScaled < aLogVector->GetLowEdgeEnergy(iTkin)) // <= ?
{
break ;
}
}
if(jMat < iMat)
{
iPlace = (iMat*(numOfMat - 1) + jMat)*fTotBin + iTkin - 1 ;
}
else
{
iPlace = (iMat*(numOfMat - 1) + jMat - 1)*fTotBin + iTkin - 1 ;
}
G4PhysicsVector* energyVector1 = (*fEnergyDistrTable)(iPlace) ;
G4PhysicsVector* energyVector2 = (*fEnergyDistrTable)(iPlace + 1) ;
G4PhysicsVector* angleVector1 = (*fAngleDistrTable)(iPlace) ;
G4PhysicsVector* angleVector2 = (*fAngleDistrTable)(iPlace + 1) ;
G4ParticleMomentum particleDir = aParticle->GetMomentumDirection() ;
if(iTkin == fTotBin) // TR plato, try from left
{
numOfTR = RandPoisson::shoot( ((*energyVector1)(0)+(*angleVector1)(0))
*chargeSq*0.5 ) ;
if(numOfTR == 0)
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
else
{
aParticleChange.SetNumberOfSecondaries(numOfTR);
for(iTR=0;iTR<numOfTR;iTR++)
{
energyPos = (*energyVector1)(0)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(energyPos >= (*energyVector1)(iTransfer)) break ;
}
energyTR = energyVector1->GetLowEdgeEnergy(iTransfer) ;
kinEnergy -= energyTR ;
aParticleChange.SetEnergyChange(kinEnergy);
anglePos = (*angleVector1)(0)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(anglePos >= (*angleVector1)(iTransfer)) break ;
}
theta = sqrt(angleVector1->GetLowEdgeEnergy(iTransfer)) ;
phi = twopi*G4UniformRand() ;
dirX = sin(theta)*cos(phi) ;
dirY = sin(theta)*sin(phi) ;
dirZ = cos(theta) ;
G4ThreeVector directionTR(dirX,dirY,dirZ) ;
directionTR.rotateUz(particleDir) ;
G4DynamicParticle* aPhotonTR = new G4DynamicParticle(G4Gamma::Gamma(),
directionTR,
energyTR ) ;
aParticleChange.AddSecondary(aPhotonTR) ;
}
}
}
else
{
if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
else // general case: Tkin between two vectors of the material
{
E1 = aLogVector->GetLowEdgeEnergy(iTkin - 1) ;
E2 = aLogVector->GetLowEdgeEnergy(iTkin) ;
W = 1.0/(E2 - E1) ;
W1 = (E2 - TkinScaled)*W ;
W2 = (TkinScaled - E1)*W ;
numOfTR = RandPoisson::shoot((((*energyVector1)(0)+(*angleVector1)(0))*W1 +
((*energyVector2)(0)+(*angleVector2)(0))*W2)
*chargeSq*0.5 ) ;
if(numOfTR == 0)
{
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
else
{
aParticleChange.SetNumberOfSecondaries(numOfTR);
for(iTR=0;iTR<numOfTR;iTR++)
{
energyPos = ((*energyVector1)(0)*W1+
(*energyVector2)(0)*W2)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(energyPos >= ((*energyVector1)(iTransfer)*W1+
(*energyVector2)(iTransfer)*W2)) break ;
}
energyTR = (energyVector1->GetLowEdgeEnergy(iTransfer))*W1+
(energyVector2->GetLowEdgeEnergy(iTransfer))*W2 ;
kinEnergy -= energyTR ;
aParticleChange.SetEnergyChange(kinEnergy);
anglePos = ((*angleVector1)(0)*W1+
(*angleVector2)(0)*W2)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(anglePos >= ((*angleVector1)(iTransfer)*W1+
(*angleVector2)(iTransfer)*W2)) break ;
}
theta = sqrt((angleVector1->GetLowEdgeEnergy(iTransfer))*W1+
(angleVector2->GetLowEdgeEnergy(iTransfer))*W2) ;
phi = twopi*G4UniformRand() ;
dirX = sin(theta)*cos(phi) ;
dirY = sin(theta)*sin(phi) ;
dirZ = cos(theta) ;
G4ThreeVector directionTR(dirX,dirY,dirZ) ;
directionTR.rotateUz(particleDir) ;
G4DynamicParticle* aPhotonTR = new G4DynamicParticle(G4Gamma::Gamma(),
directionTR,
energyTR ) ;
aParticleChange.AddSecondary(aPhotonTR) ;
}
}
}
}
return &aParticleChange ;
}
////////////////////////////////////////////////////////////////////////////
//
// Test function for checking of PostStepDoIt random preparation of TR photon
// energy
//
G4double
G4ForwardXrayTR::GetEnergyTR(G4int iMat, G4int jMat, G4int iTkin) const
{
G4int iPlace, numOfMat, numOfTR, iTR, iTransfer ;
G4double energyTR = 0.0 ; // return this value for no TR photons
G4double energyPos ;
G4double W1, W2, E1, E2 ;
static
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
numOfMat = theMaterialTable->length() ;
// The case of equal or approximate (in terms of plasma energy) materials
// No TR photons ?!
if ( iMat == jMat
|| (*theMaterialTable)(iMat)->GetState() ==
(*theMaterialTable)(jMat)->GetState()
||( (*theMaterialTable)(iMat)->GetState() == kStateSolid
&& (*theMaterialTable)(jMat)->GetState() == kStateLiquid )
||( (*theMaterialTable)(iMat)->GetState() == kStateLiquid
&& (*theMaterialTable)(jMat)->GetState() == kStateSolid ) )
{
return energyTR ;
}
if(jMat < iMat)
{
iPlace = (iMat*(numOfMat - 1) + jMat)*fTotBin + iTkin - 1 ;
}
else
{
iPlace = (iMat*(numOfMat - 1) + jMat - 1)*fTotBin + iTkin - 1 ;
}
G4PhysicsVector* energyVector1 = (*fEnergyDistrTable)(iPlace) ;
G4PhysicsVector* energyVector2 = (*fEnergyDistrTable)(iPlace + 1) ;
if(iTkin == fTotBin) // TR plato, try from left
{
numOfTR = RandPoisson::shoot( (*energyVector1)(0) ) ;
if(numOfTR == 0)
{
return energyTR ;
}
else
{
for(iTR=0;iTR<numOfTR;iTR++)
{
energyPos = (*energyVector1)(0)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(energyPos >= (*energyVector1)(iTransfer)) break ;
}
energyTR += energyVector1->GetLowEdgeEnergy(iTransfer) ;
}
}
}
else
{
if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
{
return energyTR ;
}
else // general case: Tkin between two vectors of the material
{ // use trivial mean half/half
W1 = 0.5 ;
W2 = 0.5 ;
numOfTR = RandPoisson::shoot( (*energyVector1)(0)*W1 +
(*energyVector2)(0)*W2 ) ;
if(numOfTR == 0)
{
return energyTR ;
}
else
{
G4cout<<"It is still OK in GetEnergyTR(int,int,int)"<<endl;
for(iTR=0;iTR<numOfTR;iTR++)
{
energyPos = ((*energyVector1)(0)*W1+
(*energyVector2)(0)*W2)*G4UniformRand() ;
for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
{
if(energyPos >= ((*energyVector1)(iTransfer)*W1+
(*energyVector2)(iTransfer)*W2)) break ;
}
energyTR += (energyVector1->GetLowEdgeEnergy(iTransfer))*W1+
(energyVector2->GetLowEdgeEnergy(iTransfer))*W2 ;
}
}
}
}
return energyTR ;
}
////////////////////////////////////////////////////////////////////////////
//
// Test function for checking of PostStepDoIt random preparation of TR photon
// theta angle relative to particle direction
//
G4double
G4ForwardXrayTR::GetThetaTR(G4int iMat, G4int jMat, G4int iTkin) const
{
G4double theta = 0.0 ;
return theta ;
}
// end of G4ForwardXrayTR implementation file --------------------------
@@ -0,0 +1,367 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4Scintillation.cc,v 2.2 1998/12/02 16:35:00 urban Exp $
// GEANT4 tag $Name: geant4-00 $
//
////////////////////////////////////////////////////////////////////////
// Scintillation Light Class Implementation
////////////////////////////////////////////////////////////////////////
//
// File: G4Scintillation.cc
// Description: Discrete Process - Generation of Scintillation Photons
// Version: 1.0
// Created: 1998-11-07
// Author: Peter Gumplinger
// Updated:
//
// mail: gum@triumf.ca
//
////////////////////////////////////////////////////////////////////////
#include "G4ios.hh"
#include "G4Scintillation.hh"
/////////////////////////
// Class Implementation
/////////////////////////
//////////////
// Operators
//////////////
// G4Scintillation::operator=(const G4Scintillation &right)
// {
// }
/////////////////
// Constructors
/////////////////
G4Scintillation::G4Scintillation(const G4String& processName)
: G4VDiscreteProcess(processName)
{
fTrackSecondariesFirst = false;
ScintillationYield = 0.0;
ScintillationTime = 0.0;
ResolutionScale = 1.0;
thePhysicsTable = NULL;
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created " << endl;
}
BuildThePhysicsTable();
}
// G4Scintillation::G4Scintillation(const G4Scintillation &right)
// {
// }
////////////////
// Destructors
////////////////
G4Scintillation::~G4Scintillation()
{
if (thePhysicsTable != NULL) {
thePhysicsTable->clearAndDestroy();
delete thePhysicsTable;
}
}
////////////
// Methods
////////////
// PostStepDoIt
// -------------
//
G4VParticleChange*
G4Scintillation::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
// This routine is called for each tracking step of a charged particle
// in a scintillator. A Gaussian-distributed number of photons is generated
// according to the scintillation yield formula, distributed evenly along
// the track segment and uniformly into 4pi.
{
aParticleChange.Initialize(aTrack);
const G4Material* aMaterial = aTrack.GetMaterial();
G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
G4ThreeVector x0 = pPreStepPoint->GetPosition();
G4ThreeVector p0 = pPreStepPoint->GetMomentumDirection();
G4double t0 = pPreStepPoint->GetGlobalTime();
G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
if (!aMaterialPropertiesTable)
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
const G4MaterialPropertyVector* Intensity =
aMaterialPropertiesTable->GetProperty("SCINTILLATION");
if (!Intensity)
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
G4double MeanNumPhotons = ScintillationYield * TotalEnergyDeposit;
G4int NumPhotons = (G4int) MeanNumPhotons +
int( ResolutionScale * RandGauss::shoot(0.0,sqrt(MeanNumPhotons)));
if (NumPhotons <= 0) {
// return unchanged particle and no secondaries
aParticleChange.SetNumberOfSecondaries(0);
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
////////////////////////////////////////////////////////////////
aParticleChange.SetNumberOfSecondaries(NumPhotons);
if (fTrackSecondariesFirst)
aParticleChange.SetStatusChange(fSuspend);
////////////////////////////////////////////////////////////////
G4double Pmin = Intensity->GetMinPhotonMomentum();
G4double Pmax = Intensity->GetMaxPhotonMomentum();
G4double dp = Pmax - Pmin;
G4int materialIndex = G4Material::GetMaterialTable()->index(aMaterial);
// Retrieve the Scintillation Integral for this material
// new G4PhysicsOrderedFreeVector allocated to hold CII's
G4PhysicsOrderedFreeVector* ScintillationIntegral =
(G4PhysicsOrderedFreeVector*)((*thePhysicsTable)(materialIndex));
// Max Scintillation Integral
G4double CIImax = ScintillationIntegral->GetMaxValue();
for (G4int i = 0; i < NumPhotons; i++) {
// Determine photon momentum
G4double CIIvalue = G4UniformRand()*CIImax;
G4double sampledMomentum =
ScintillationIntegral->GetEnergy(CIIvalue);
if (verboseLevel>1) {
G4cout << "sampledMomentum = " << sampledMomentum << endl;
G4cout << "CIIvalue = " << CIIvalue << endl;
}
// Generate random photon direction
G4double cost = 1. - 2.*G4UniformRand();
G4double sint = sqrt((1.-cost)*(1.-cost));
G4double phi = 2*M_PI*G4UniformRand();
G4double sinp = sin(phi);
G4double cosp = cos(phi);
G4double px = sint*cosp;
G4double py = sint*sinp;
G4double pz = cost;
// Create photon momentum direction vector
G4ParticleMomentum photonMomentum(px, py, pz);
// Determine polarization of new photon
G4double sx = cost*cosp;
G4double sy = cost*sinp;
G4double sz = -sint;
G4ThreeVector photonPolarization(sx, sy, sz);
G4ThreeVector perp = photonMomentum.cross(photonPolarization);
phi = 2*M_PI*G4UniformRand();
sinp = sin(phi);
cosp = cos(phi);
photonPolarization = cosp * photonPolarization + sinp * perp;
photonPolarization = photonPolarization.unit();
// Generate a new photon:
G4DynamicParticle* aScintillationPhoton =
new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(),
photonMomentum);
aScintillationPhoton->SetPolarization
(photonPolarization.x(),
photonPolarization.y(),
photonPolarization.z());
aScintillationPhoton->SetKineticEnergy(sampledMomentum);
// Generate new G4Track object:
G4double delta = G4UniformRand() * aStep.GetStepLength();
G4ThreeVector aSecondaryPosition = x0 + delta * p0;
G4double deltaTime = delta /
((pPreStepPoint->GetVelocity()+
pPostStepPoint->GetVelocity())/2.);
deltaTime = deltaTime -
ScintillationTime * log( G4UniformRand() );
G4double aSecondaryTime = t0 + deltaTime;
G4Track* aSecondaryTrack =
new G4Track(aScintillationPhoton,aSecondaryTime,aSecondaryPosition);
aSecondaryTrack->SetTouchable(pPreStepPoint->GetTouchable());
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
aParticleChange.AddSecondary(aSecondaryTrack);
}
if (verboseLevel>0) {
G4cout << "\n Exiting from G4Scintillation::DoIt -- NumberOfSecondaries = "
<< aParticleChange.GetNumberOfSecondaries() << endl;
}
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
// BuildThePhysicsTable for the scintillation process
// --------------------------------------------------
//
void G4Scintillation::BuildThePhysicsTable()
{
if (thePhysicsTable) return;
const G4MaterialTable* theMaterialTable =
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
// create new physics table
thePhysicsTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
for (G4int i=0 ; i < numOfMaterials; i++)
{
G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
// Retrieve vector of scintillation wavelength intensity
// for the material from the material's optical
// properties table
G4Material* aMaterial = (*theMaterialTable)(i);
G4MaterialPropertiesTable* aMaterialPropertiesTable =
aMaterial->GetMaterialPropertiesTable();
if (aMaterialPropertiesTable) {
G4MaterialPropertyVector* theScintillationLightVector =
aMaterialPropertiesTable->GetProperty("SCINTILLATION");
if (theScintillationLightVector) {
// Retrieve the first intensity point in vector
// of (photon momentum, intensity) pairs
theScintillationLightVector->ResetIterator();
++(*theScintillationLightVector); // advance to 1st entry
G4double currentIN = theScintillationLightVector->
GetProperty();
if (currentIN >= 0.0) {
// Create first (photon momentum, Scintillation
// Integral pair
G4double currentPM = theScintillationLightVector->
GetPhotonMomentum();
G4double currentCII = 0.0;
aPhysicsOrderedFreeVector->
InsertValues(currentPM , currentCII);
// Set previous values to current ones prior to loop
G4double prevPM = currentPM;
G4double prevCII = currentCII;
G4double prevIN = currentIN;
// loop over all (photon momentum, intensity)
// pairs stored for this material
while(++(*theScintillationLightVector))
{
currentPM = theScintillationLightVector->
GetPhotonMomentum();
currentIN=theScintillationLightVector->
GetProperty();
currentCII = 0.5 * (prevIN + currentIN);
currentCII = prevCII +
(currentPM - prevPM) * currentCII;
aPhysicsOrderedFreeVector->
InsertValues(currentPM, currentCII);
prevPM = currentPM;
prevCII = currentCII;
prevIN = currentIN;
}
}
}
}
// The scintillation integral for a given material
// will be inserted in thePhysicsTable
// according to the position of the material in
// the material table.
thePhysicsTable->insertAt(i,aPhysicsOrderedFreeVector);
}
}
// GetMeanFreePath
// ---------------
//
G4double G4Scintillation::GetMeanFreePath(const G4Track& aTrack,
G4double ,
G4ForceCondition* condition)
{
*condition = Forced;
return DBL_MAX;
}
@@ -0,0 +1,201 @@
// This code implementation is the intellectual property of
// the RD44 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.
//
// $Id: G4TransitionRadiation.cc,v 2.2 1998/11/27 13:37:02 grichine Exp $
// GEANT4 tag $Name: geant4-00 $
//
// G4TransitionRadiation class -- implementation file
// GEANT 4 class implementation file --- Copyright CERN 1995
// CERN Geneva Switzerland
// For information related to this code, please, contact
// CERN, CN Division, ASD Group
// History:
// 1st version 11.09.97 V. Grichine (Vladimir.Grichine@cern.ch )
// 2nd version 16.12.97 V. Grichine
#include <math.h>
// #include "G4ios.hh"
// #include <fstream.h>
// #include <stdlib.h>
#include "G4TransitionRadiation.hh"
#include "G4Material.hh"
// Init gamma array
// Local constants
const G4int G4TransitionRadiation::fSympsonNumber = 100 ;
const G4int G4TransitionRadiation::fGammaNumber = 15 ;
const G4int G4TransitionRadiation::fPointNumber = 100 ;
///////////////////////////////////////////////////////////////////////
//
// Constructor for selected couple of materials
//
G4TransitionRadiation::
G4TransitionRadiation( const G4String& processName )
: G4VDiscreteProcess(processName)
{
// fMatIndex1 = pMat1->GetIndex() ;
// fMatIndex2 = pMat2->GetIndex() ;
}
//////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4TransitionRadiation::~G4TransitionRadiation()
{
;
}
///////////////////////////////////////////////////////////////////
//
// Sympson integral of TR spectral-angle density over energy between
// the limits energy 1 and energy2 at fixed varAngle = 1 - cos(Theta)
G4double
G4TransitionRadiation::IntegralOverEnergy( G4double energy1,
G4double energy2,
G4double varAngle ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(energy2 - energy1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += SpectralAngleTRdensity(energy1 + 2*i*h,varAngle) ;
sumOdd += SpectralAngleTRdensity(energy1 + (2*i - 1)*h,varAngle) ;
}
sumOdd += SpectralAngleTRdensity(energy1 + (2*fSympsonNumber - 1)*h,varAngle) ;
return h*( SpectralAngleTRdensity(energy1,varAngle)
+ SpectralAngleTRdensity(energy2,varAngle)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
///////////////////////////////////////////////////////////////////
//
// Sympson integral of TR spectral-angle density over energy between
// the limits varAngle1 and varAngle2 at fixed energy
G4double
G4TransitionRadiation::IntegralOverAngle( G4double energy,
G4double varAngle1,
G4double varAngle2 ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += SpectralAngleTRdensity(energy,varAngle1 + 2*i*h) ;
sumOdd += SpectralAngleTRdensity(energy,varAngle1 + (2*i - 1)*h) ;
}
sumOdd += SpectralAngleTRdensity(energy,varAngle1 + (2*fSympsonNumber - 1)*h) ;
return h*( SpectralAngleTRdensity(energy,varAngle1)
+ SpectralAngleTRdensity(energy,varAngle2)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
///////////////////////////////////////////////////////////////////
//
// The number of transition radiation photons generated in the
// angle interval between varAngle1 and varAngle2
//
G4double G4TransitionRadiation::
AngleIntegralDistribution( G4double varAngle1,
G4double varAngle2 ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += IntegralOverEnergy(fMinEnergy,
fMinEnergy +0.3*(fMaxEnergy-fMinEnergy),
varAngle1 + 2*i*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + 2*i*h);
sumOdd += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1 + (2*i - 1)*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + (2*i - 1)*h) ;
}
sumOdd += IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1 + (2*fSympsonNumber - 1)*h)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1 + (2*fSympsonNumber - 1)*h) ;
return h*(IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle1)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle1)
+ IntegralOverEnergy(fMinEnergy,
fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
varAngle2)
+ IntegralOverEnergy(fMinEnergy + 0.3*(fMaxEnergy - fMinEnergy),
fMaxEnergy,
varAngle2)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
///////////////////////////////////////////////////////////////////
//
// The number of transition radiation photons, generated in the
// energy interval between energy1 and energy2
//
G4double G4TransitionRadiation::
EnergyIntegralDistribution( G4double energy1,
G4double energy2 ) const
{
G4int i ;
G4double h , sumEven = 0.0 , sumOdd = 0.0 ;
h = 0.5*(energy2 - energy1)/fSympsonNumber ;
for(i=1;i<fSympsonNumber;i++)
{
sumEven += IntegralOverAngle(energy1 + 2*i*h,0.0,0.01*fMaxTheta )
+ IntegralOverAngle(energy1 + 2*i*h,0.01*fMaxTheta,fMaxTheta);
sumOdd += IntegralOverAngle(energy1 + (2*i - 1)*h,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1 + (2*i - 1)*h,0.01*fMaxTheta,fMaxTheta) ;
}
sumOdd += IntegralOverAngle(energy1 + (2*fSympsonNumber - 1)*h,
0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1 + (2*fSympsonNumber - 1)*h,
0.01*fMaxTheta,fMaxTheta) ;
return h*(IntegralOverAngle(energy1,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy1,0.01*fMaxTheta,fMaxTheta)
+ IntegralOverAngle(energy2,0.0,0.01*fMaxTheta)
+ IntegralOverAngle(energy2,0.01*fMaxTheta,fMaxTheta)
+ 4.0*sumOdd + 2.0*sumEven )/3.0 ;
}
// end of G4TransitionRadiation implementation file --------------------------