Import Geant4 11.2.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2023-06-30 09:09:57 +02:00
parent aef78ca386
commit dd1f179cda
3780 changed files with 212808 additions and 142780 deletions
@@ -0,0 +1,16 @@
# Category param History
See `CONTRIBUTING.rst` for details of **required** info/format for each entry,
which **must** added in reverse chronological order (newest at the top).
It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-06-15 Gabriele Cosmo (fastsimchanneling-V11-01-02)
- Fixed compilation warnings for implicit type conversions on macOS/XCode 14.1.
## 2023-06-08 Alexei Sytov (fastsimchanneling-V11-01-01)
- Fix Coverity defects
## 2023-05-17 Alexei Sytov (fastsimchanneling-V11-01-00)
- Created Channeling FastSimulation model and Baier Katkov method
@@ -0,0 +1,304 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#ifndef G4BaierKatkov_h
#define G4BaierKatkov_h 1
#include "globals.hh"
#include <CLHEP/Units/SystemOfUnits.h>
#include <vector>
#include "G4ThreeVector.hh"
#include "G4VFastSimulationModel.hh"
/** \file G4BaierKatkov.hh
* \brief Definition of the G4BaierKatkov class
* This class is designed for the calculation of radiation probability, radiation point
* and the parameters of the photon produced as well as spectrum accumulation using
* the Baier-Katkov integral:
* V. N. Baier, V. M. Katkov, and V. M. Strakhovenko,
* Electromagnetic Processes at High Energies in Oriented Single Crystals
* (World Scientific, Singapore, 1998).
*/
class G4BaierKatkov
{
public:
// default constructor
G4BaierKatkov();
// destructor
~G4BaierKatkov() = default;
/**
You may call DoRadiation at each step of your trajectory
CAUTION: please ensure that your steps are physically small enough for calculation
of the radiation type you are interested in
CAUTION: do ResetRadIntegral() before the start of a new trajectory
1) change some model defaults if necessary (SetSinglePhotonRadiationProbabilityLimit,
SetNSmallTrajectorySteps, SetSpectrumEnergyRange)
2) call DoRadiation at each step of your trajectory
3) if DoRadiation returns TRUE, this means that a photon is produced (not added
as a secondary yet) and its parameters are calculated.
4) You may generate a new photon using GeneratePhoton either with
the parameters calculated in DoRadiation or your own parameters.
CAUTION: By now GeneratePhoton works only for a FastSim model
5) Use GetPhotonEnergyInSpectrum() and GetTotalSpectrum() to return calculated
total spectrum (all the photons altogether)
Caution: is not normalized on the event number
6) Get the charged particle parameters in the radiation point:
GetParticleNewTotalEnergy(),
GetParticleNewAngleX(), GetParticleNewAngleY(),
GetNewGlobalTime(),
GetParticleNewCoordinateXYZ()
*/
///get functions
/// get maximal radiation probability to preserve single photon radiation
G4double GetSinglePhotonRadiationProbabilityLimit()
{return fSinglePhotonRadiationProbabilityLimit;}
///CAUTION! : use the get functions below ONLY AFTER the call of DoRadiation
/// and ONLY IF IT RETURNS true
///total probability of radiation: needs calculation of DoRadiation first
G4double GetTotalRadiationProbability(){return fTotalRadiationProbability;}
///get new parameters of the particle
///(the parameters at the point of radiation emission)
///needs calculation of DoRadiation first
G4double GetParticleNewTotalEnergy(){return fNewParticleEnergy;}
G4double GetParticleNewAngleX(){return fNewParticleAngleX;}
G4double GetParticleNewAngleY(){return fNewParticleAngleY;}
G4double GetNewGlobalTime(){return fNewGlobalTime;}
const G4ThreeVector& GetParticleNewCoordinateXYZ(){return fNewParticleCoordinateXYZ;}
///get photon energies (x-value in spectrum)
const std::vector<G4double>& GetPhotonEnergyInSpectrum(){return fPhotonEnergyInSpectrum;}
///get fTotalSpectrum after finishing the trajectory part with DoRadiation
const std::vector<G4double>& GetTotalSpectrum(){return fTotalSpectrum;}
///set functions
///set maximal radiation probability to preserve single photon radiation
void SetSinglePhotonRadiationProbabilityLimit(G4double wmax)
{fSinglePhotonRadiationProbabilityLimit = wmax;}
///number of steps in a trajectory small piece before
///the next call of the radiation integral
void SetNSmallTrajectorySteps(G4double nSmallTrajectorySteps)
{fNSmallTrajectorySteps = nSmallTrajectorySteps;}
///reinitialize intermediate integrals fFa, fSs, fSc, fSsx, fSsy, fScx, fScy;
///reset radiation integral internal variables to defaults;
///reset the trajectory and radiation probability along the trajectory
void ResetRadIntegral();
///setting the number of photons in sampling of Baier-Katkov Integral
///(MC integration by photon energy and angles <=> photon momentum)
void SetSamplingPhotonsNumber(G4double nPhotons){fNMCPhotons = nPhotons;}
///CAUTION, the bins width is logarithmic
///Do not worry if the maximal energy > particle energy.
///This elements of spectrum with non-physical energies
///will not be processed (they will be 0).
void SetSpectrumEnergyRange(G4double emin,
G4double emax,
G4int numberOfBins);
/// SetSpectrumEnergyRange also calls ResetRadIntegral()
void SetMinPhotonEnergy(G4double emin){SetSpectrumEnergyRange(emin,
fMaxPhotonEnergy,
fNBinsSpectrum);}
void SetMaxPhotonEnergy(G4double emax){SetSpectrumEnergyRange(fMinPhotonEnergy,
emax,
fNBinsSpectrum);}
void SetNBinsSpectrum(G4int nbin){SetSpectrumEnergyRange(fMinPhotonEnergy,
fMaxPhotonEnergy,
nbin);}
/// add the new elements of the trajectory, calculate radiation in a crystal
/// see complete description in G4BaierKatkov::DoRadiation
/// calls RadIntegral and all the necessary functions
/// sets the parameters of a photon produced (if any)
/// using SetPhotonProductionParameters()
/// returns true in the case of photon generation, false if not
G4bool DoRadiation(G4double etotal, G4double mass,
G4double angleX, G4double angleY,
G4double angleScatteringX, G4double angleScatteringY,
G4double step, G4double globalTime,
G4ThreeVector coordinateXYZ,
G4bool flagEndTrajectory=false);
/// generates secondary photon belonging to fastStep with variables
/// photon energy, momentum direction, coordinates and global time
/// CALCULATED IN DoRadiation => USE IT ONLY AFTER DoRadiation returns true
void GeneratePhoton(G4FastStep &fastStep);
private:
///set functions
///function setting the photon sampling parameters in the Baier-Katkov integral;
///only the maximal energy is set, while fMinPhotonEnergy is used as a minimal energy;
///the angles set the angular distribution (the tails are infinite)
void SetPhotonSamplingParameters(G4double ekin,
G4double minPhotonAngleX, G4double maxPhotonAngleX,
G4double minPhotonAngleY, G4double maxPhotonAngleY);
///main functions:
///generation of the photons in sampling of Baier-Katkov Integral
///(MC integration by photon energy and angles <=> by photon momentum)
void GeneratePhotonSampling();
///Baier-Katkov method: calculation of integral, spectrum, full probability;
///returns the total radiation probability;
///calculates the radiation spectrum on this trajectory piece
G4double RadIntegral(G4double etotal, G4double mass,
std::vector<G4double> &vectorParticleAnglesX,
std::vector<G4double> &vectorParticleAnglesY,
std::vector<G4double> &vectorScatteringAnglesX,
std::vector<G4double> &vectorScatteringAnglesY,
std::vector<G4double> &vectorSteps,
G4int imin);
///set photon production parameters (returns false if no photon produced)
///accumulates fTotalSpectrum
///CAUTION: it is an accessory function of DoRadiation, do not use it separately
G4bool SetPhotonProductionParameters(G4double etotal, G4double mass);
G4int FindVectorIndex(std::vector<G4double> &myvector, G4double value);
G4double fTotalRadiationProbability = 0.;
G4double fSinglePhotonRadiationProbabilityLimit=0.05;//Maximal radiation
//probability to preserve single photon radiation
//number of steps in a trajectory piece before the next call of the radiation integral
G4int fNSmallTrajectorySteps=1000;
///trajectory element No (the first element of the array feeded in RadIntegral)
G4int fImin0 = 0;
///number of Monte Carlo points of integration on photon angles
G4int fNMCPhotons =150;
///the number of bins in photon spectrum
G4int fNBinsSpectrum = 110;
G4double fMinPhotonEnergy = 0.1*CLHEP::MeV;//min energy in spectrum output
G4double fMaxPhotonEnergy = 1*CLHEP::GeV; //max energy in spectrum output
G4double fLogEmaxdEmin = 1.;// = log(fMaxPhotonEnergy/fMinPhotonEnergy),
// 1/normalizing coefficient in
// 1/E distribution between
// fMinPhotonEnergy and fMaxPhotonEnergy
// is used only for spectrum output, not for simulations
//(we take bremsstrahlung for photon sampling)
G4double fLogEdEmin = 1.; // = log(E/fMinPhotonEnergy), the same as fLogEmaxdEmin
// but with the particle energy as the maximal limit
///number of trajectories
//(at each of the Baier-Katkov Integral is calculated for the same photons)
G4int fItrajectories = 0;
G4double fEph0=0; //energy of the photon produced
G4ThreeVector PhMomentumDirection; //momentum direction of the photon produced
///Radiation integral variables
G4double fMeanPhotonAngleX =0.; //average angle of radiated photon direction
//in sampling, x-plane
G4double fParamPhotonAngleX=1.e-3*CLHEP::rad; //a parameter radiated photon
//sampling distribution, x-plane
G4double fMeanPhotonAngleY =0.; //average angle of radiated photon direction
//in sampling, y-plane
G4double fParamPhotonAngleY=1.e-3*CLHEP::rad; //a parameter radiated photon
//sampling distribution, y-plane
///new particle parameters (the parameters at the point of radiation emission)
G4double fNewParticleEnergy=0;
G4double fNewParticleAngleX=0;
G4double fNewParticleAngleY=0;
G4double fNewGlobalTime=0;
G4ThreeVector fNewParticleCoordinateXYZ;
///sampling of the energy and the angles of a photon emission
///(integration variables, Monte Carlo integration)
std::vector<G4double> fPhotonEnergyInIntegral;
std::vector<G4double> fPhotonAngleInIntegralX;
std::vector<G4double> fPhotonAngleInIntegralY;
std::vector<G4double> fPhotonAngleNormCoef;
///spectrum bin index for each photon
std::vector<G4double> fIBinsSpectrum;
///the vector of the discrete CDF of the radiation of sampling photons
std::vector<G4double> fPhotonProductionCDF;
///vectors of the trajectory
std::vector<G4double> fParticleAnglesX;
std::vector<G4double> fParticleAnglesY;
std::vector<G4double> fScatteringAnglesX;
std::vector<G4double> fScatteringAnglesY;
std::vector<G4double> fSteps;
std::vector<G4double> fGlobalTimes;
std::vector<G4ThreeVector> fParticleCoordinatesXYZ;
///intermediate integrals (different for each photon energy value)!!!
std::vector<G4double> fFa;//phase
std::vector<G4double> fSs;
std::vector<G4double> fSc;
std::vector<G4double> fSsx;
std::vector<G4double> fSsy;
std::vector<G4double> fScx;
std::vector<G4double> fScy;
///output
std::vector<G4double> fPhotonEnergyInSpectrum; //energy values in spectrum
std::vector<G4int> fNPhotonsPerBin; //number of photons per spectrum bin
//(accumulating during total run)
std::vector<G4double> fSpectrum; //spectrum normalized by the total radiation probability
//of one particle at one call of RadIntegral
std::vector<std::vector<G4double>> fAccumSpectrum; //accumulate Spectrum during
//the part of a trajectory
std::vector<G4double> fAccumTotalSpectrum; //spectrum normalized by the total radiation
//probability summed
//for all the particles (is not divided
//of one particle number fNPhotonsPerBin)
std::vector<G4double> fTotalSpectrum; //spectrum normalized by
//the total radiation probability summed
//for all the particles
//(is divided by the photon number fNPhotonsPerBin)
//multiplied by the number of trajectories
//(fItrajectories)
std::vector<G4double> fImax0; //trajectory element numbers at the end of each small piece
//G4double just for security of some operations
///total radiation probability along this trajectory
std::vector<G4double> fTotalRadiationProbabilityAlongTrajectory;
};
#endif
@@ -0,0 +1,113 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#ifndef G4ChannelingFastSimCrystalData_h
#define G4ChannelingFastSimCrystalData_h 1
#include "G4ios.hh"
#include "globals.hh"
#include <CLHEP/Units/SystemOfUnits.h>
#include "G4ThreeVector.hh"
#include "Randomize.hh"
#include "G4Material.hh"
#include <unordered_map>
#include "G4VChannelingFastSimCrystalData.hh"
#include "G4ChannelingFastSimInterpolation.hh"
/** \file G4ChannelingFastSimCrystalData.hh
* \brief Definition of the G4ChannelingFastSimCrystalData class
* The class inherits G4VChannelingFastSimCrystalData containing the data and properties
* related to the crystal lattice.
* The functions related to the crystal geometry (transformation of coordinates and angles
* from the reference system of the bounding box of the local volume to
* the crystal lattice co-rotating reference system and vice versa) and
* initialization function SetMaterialProperties are compiled in this class.
*/
class G4ChannelingFastSimCrystalData : public G4VChannelingFastSimCrystalData
{
public:
G4ChannelingFastSimCrystalData();
virtual ~G4ChannelingFastSimCrystalData() = default;
public:
///find and upload crystal lattice input files, calculate all the basic values
///(to do only once)
void SetMaterialProperties(const G4Material* crystal, const G4String &lattice);
///calculate the coordinates in the co-rotating reference system
///within a channel (periodic cell)
///(connected with crystal planes/axes either bent or straight)
G4ThreeVector CoordinatesFromBoxToLattice(const G4ThreeVector &pos0);
///calculate the coordinates in the Box reference system
///(connected with the bounding box of the volume)
G4ThreeVector CoordinatesFromLatticeToBox(const G4ThreeVector &pos);
///change the channel if necessary, recalculate x o y
G4ThreeVector ChannelChange(G4double &x, G4double &y, G4double &z);
///calculate the horizontal angle in the co-rotating reference system
///within a channel (periodic cell)
///(connected with crystal planes/axes either bent or straight)
G4double AngleXFromBoxToLattice(G4double tx, G4double z){return tx-AngleXShift(z);}
///calculate the horizontal angle in the Box reference system
///(connected with the bounding box of the volume)
G4double AngleXFromLatticeToBox(G4double tx, G4double z){return tx+AngleXShift(z);}
///auxialiary function to transform the horizontal angle
G4double AngleXShift(G4double z){return fMiscutAngle + z*fCurv;}
private:
///variables
G4int fNsteps=353;//number of steps per channeling oscillation
G4double fR0=1.1*CLHEP::fermi;//*A^(1/3) - radius of nucleus
///Values related to coordinate transformation
long long int fNChannelx=0;//horizontal number of channel
//(either straight of bent) inside the box
long long int fNChannely=0;//vertical number of channel (either straight of bent)
//inside the box; =0 in the case of planes
///values related to the crystal lattice
G4int fNpointsx=0,fNpointsy=0;// number of horizontal and vertical nodes of interpolation
G4double fDx=0, fDy=0;// channel (periodic cell)
//horizontal and vertical dimensions
///fundamental constants of material
std::vector <G4double> fN0; // nuclear concentration
std::vector <G4double> fU1; // amplitude of thermal oscillations
std::vector <G4double> fZ1;//atomic number of each element
std::vector <G4double> fAN; //atomic mass of each element
};
#endif
@@ -0,0 +1,96 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#ifndef G4ChannelingFastSimInterpolation_h
#define G4ChannelingFastSimInterpolation_h
#include "G4PhysicsVector.hh"
#include "G4Physics2DVector.hh"
#include "G4ThreeVector.hh"
#include "G4PhysicsLinearVector.hh"
/** \file G4ChannelingFastSimInterpolation.hh
* \brief Definition of the G4ChannelingFastSimInterpolation class
* The class includes spline interpolation coefficients for the important functions
* needed in Channeling FastSimulation model, i.e. electric fields, nuclear and
* electron densities and minimum energy of ionization. All the functions have
* transverse coordinates as arguments (x for crystal planes, x and y for crystal axes).
* All the functions are calculated in the co-rotating reference system (along crystal
* planes/axes).
*/
class G4ChannelingFastSimInterpolation {
public:
G4ChannelingFastSimInterpolation(G4double dx0,
G4double dy0,
G4int nPointsx0,
G4int nPointsy0,
G4int iModel0);
~G4ChannelingFastSimInterpolation() = default;
///Get Spline Function
G4double GetIF(G4double xx, G4double yy);
///Set spline coefficients
void SetCoefficients1D(G4double AI0,
G4double BI0,
G4double CI0,
G4double DI0,
G4int i);
void SetCoefficients2D(G4double AI3D0,
G4double BI3D0,
G4double CI3D0,
G4int i,
G4int j,
G4int k);
private:
G4double Spline1D(G4double xx);
G4double Spline2D(G4double xx, G4double yy);// cubic spline of 2-variable function
G4double fDx=0, fDy=0; //channel width and height
G4double fStepi=0, fStepj=0; //interpolation steps in x and y, respectively
G4double fStepi2=0; //=fStepi*fStepi
G4int nPointsx=0, nPointsy=0; //number of interpolation nodes in x and y, respectively
std::vector <G4double> fAI;
std::vector <G4double> fBI;
std::vector <G4double> fCI;
std::vector <G4double> fDI;
std::vector<std::vector<G4double>> fAI3D;
std::vector<std::vector<G4double>> fBI3D;
std::vector<std::vector<G4double>> fCI3D;
std::vector<std::vector<G4double>> fAI3D3;
std::vector<std::vector<G4double>> fBI3D3;
std::vector<std::vector<G4double>> fCI3D3;
G4int iModel=1;
};
#endif
@@ -0,0 +1,142 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#ifndef G4ChannelingFastSimModel_h
#define G4ChannelingFastSimModel_h 1
#include "G4VFastSimulationModel.hh"
#include "G4Step.hh"
#include "G4TouchableHandle.hh"
#include <vector>
#include <CLHEP/Units/SystemOfUnits.h>
#include <CLHEP/Units/PhysicalConstants.h>
#include "G4ChannelingFastSimCrystalData.hh"
#include <unordered_map>
#include "G4BaierKatkov.hh"
#include "G4LogicalVolume.hh"
#include "G4ParticleTable.hh"
/** \file G4ChannelingFastSimModel.hh
* \brief Definition of the G4ChannelingFastSimModel class
* FastSimulation Channeling model: calculates charge particle trajectories
* in oriented crystals in the field of crystal planes/axes either straight or bent.
* It is also possible to simulate radiation using Baier-Katkov method.
*/
class G4ChannelingFastSimModel : public G4VFastSimulationModel
{
public:
// Constructor, destructor
G4ChannelingFastSimModel (const G4String&, G4Region*);
G4ChannelingFastSimModel (const G4String&);
~G4ChannelingFastSimModel ();
/// -- IsApplicable
G4bool IsApplicable(const G4ParticleDefinition&) override;
/// -- ModelTrigger
G4bool ModelTrigger(const G4FastTrack &) override;
/// -- User method DoIt
void DoIt(const G4FastTrack&, G4FastStep&) override;
///special functions
void Input(const G4Material* crystal, const G4String &lattice);
void RadiationModelActivate();
G4ChannelingFastSimCrystalData* GetCrystalData() {return fCrystalData;}
G4BaierKatkov* GetRadiationModel() {return fBaierKatkov;}
G4bool GetIfRadiationModelActive(){return fRad;}
///set cuts
void SetLowKineticEnergyLimit(G4double ekinetic, const G4String& particleName)
{fLowEnergyLimit[particleTable->FindParticle(particleName)->
GetParticleDefinitionID()] = ekinetic;}
void SetLindhardAngleNumberHighLimit(G4double angleNumber, const G4String& particleName)
{fLindhardAngleNumberHighLimit[particleTable->FindParticle(particleName)->
GetParticleDefinitionID()]=angleNumber;}
void SetDefaultLowKineticEnergyLimit(G4double ekinetic)
{fDefaultLowEnergyLimit=ekinetic;}
void SetDefaultLindhardAngleNumberHighLimit(G4double angleNumber)
{fDefaultLindhardAngleNumberHighLimit=angleNumber;}
/// get the maximal number of photons that can be produced per fastStep
/// Caution: is redundant, if the radiation model is not activated
void SetMaxPhotonsProducedPerStep(G4double nPhotons)
{fMaxPhotonsProducedPerStep=nPhotons;}
///get cuts
G4double GetLowKineticEnergyLimit(const G4String& particleName)
{return GetLowKineticEnergyLimit(particleTable->
FindParticle(particleName)->
GetParticleDefinitionID());}
G4double GetLindhardAngleNumberHighLimit(const G4String& particleName)
{return GetLindhardAngleNumberHighLimit(particleTable->
FindParticle(particleName)->
GetParticleDefinitionID());}
//the same functions but using particleDefinitionID (needed for faster model execution)
G4double GetLowKineticEnergyLimit(G4int particleDefinitionID)
{return (fLowEnergyLimit.count(particleDefinitionID) == 1)
? fLowEnergyLimit[particleDefinitionID]
: fDefaultLowEnergyLimit;}
G4double GetLindhardAngleNumberHighLimit(G4int particleDefinitionID)
{return (fLindhardAngleNumberHighLimit.count(particleDefinitionID) == 1)
? fLindhardAngleNumberHighLimit[particleDefinitionID]
: fDefaultLindhardAngleNumberHighLimit;}
/// get the maximal number of photons that can be produced per fastStep
G4int GetMaxPhotonsProducedPerStep(){return fMaxPhotonsProducedPerStep;}
private:
G4ChannelingFastSimCrystalData* fCrystalData{nullptr};
G4BaierKatkov* fBaierKatkov{nullptr};
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
///flag of radiation model
G4bool fRad = false;
/// maps of cuts
std::unordered_map<G4int, G4double> fLowEnergyLimit;
std::unordered_map<G4int, G4double> fLindhardAngleNumberHighLimit;
G4double fDefaultLowEnergyLimit = 200*CLHEP::MeV;
G4double fDefaultLindhardAngleNumberHighLimit = 100.;
/// the maximal number of photons that can be produced per fastStep
G4int fMaxPhotonsProducedPerStep=1000.;
};
#endif
@@ -0,0 +1,302 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
#ifndef G4VChannelingFastSimCrystalData_h
#define G4VChannelingFastSimCrystalData_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "G4ThreeVector.hh"
#include "Randomize.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4VSolid.hh"
#include <unordered_map>
#include "G4ChannelingFastSimInterpolation.hh"
/** \file G4VChannelingFastSimCrystalData.hh
* \brief Definition of the G4VChannelingFastSimCrystalData class
* The class contains the data and properties related to the crystal lattice as well as
* functions to simulate of important physical processes, i.e. coulomb scattering on
* screened atomic potential, on single electrons and ionization energy losses;
* functions of electric fields, nuclear and electron densities and minimum energy
* of ionization (the corresponding interpolation coefficients are in
* G4ChannelingFastSimInterpolation).
* The functions related to the crystal geometry (transformation of coordinates and angles
* from the reference system of the bounding box of the local volume to
* the crystal lattice co-rotating reference system and vice versa) and
* initialization function SetMaterialProperties are created as virtual to make
* material data input and geometry functions flexible for modification.
*/
class G4VChannelingFastSimCrystalData{
public:
G4VChannelingFastSimCrystalData();
virtual ~G4VChannelingFastSimCrystalData();
///electric fields produced by crystal lattice
G4double Ex(G4double x,G4double y) {return (fElectricFieldX->GetIF(x,y))*(-fZ2/fPV);}
G4double Ey(G4double x,G4double y) {return (fElectricFieldY->GetIF(x,y))*(-fZ2/fPV);}
///electron density function
G4double ElectronDensity(G4double x,G4double y)
{
G4double nel0=fElectronDensity->GetIF(x,y);
if(nel0<0.) {nel0=0.;}//exception, errors of interpolation functions
return nel0;
}
///minimum energy of ionization function
G4double MinIonizationEnergy(G4double x,G4double y)
{return fMinIonizationEnergy->GetIF(x,y);}
///nuclear density function (normalized to average nuclear density)
G4double NuclearDensity(G4double x,G4double y, G4int ielement)
{return std::abs(fNucleiDensity[ielement]->GetIF(x,y));}
//abs to describe exception, errors of interpolation functions,
//don't put it =0, otherwise division on 0 in CoulombAtomicScattering
///Calculate the value of the Lindhard angle (!!! the value for a straight crystal)
G4double GetLindhardAngle(G4double etotal, G4double mass);
///Calculate the value of the Lindhard angle (!!! the value for a straight crystal)
G4double GetLindhardAngle();//return the Lindhard angle value calculated in
//SetParticleProperties
///Calculate simulation step (standard value for channeling particles and
///reduced value for overbarrier particles)
G4double GetSimulationStep(G4double tx,G4double ty);
///Calculate maximal simulation step (standard value for channeling particles)
G4double GetMaxSimulationStep(G4double etotal, G4double mass);
///get particle velocity/c
G4double GetBeta(){return fBeta;}
G4int GetNelements() {return fNelements;}
G4int GetModel() {return iModel;}//=1 for planes, =2 for axes
///get bending angle of the crystal planes/axes
///(default BendingAngle=0 => straight crystal);
G4double GetBendingAngle(){return fBendingAngle;}
///fBendingAngle MAY BE NOT THE SAME AS THE BENDING ANGLE OF THE CRYSTAL VOLUME:
///THE VOLUME OF A BENT CRYSTAL MAY BE G4Box, while the planes/axes inside may be bent
G4double GetMiscutAngle(){return fMiscutAngle;}
///get crystal curvature
G4double GetCurv(){return fCurv;}
///find and upload crystal lattice input files, calculate all the basic values
///(to do only once)
virtual void SetMaterialProperties(const G4Material* crystal,
const G4String &lattice) = 0;
///set geometry parameters from current logical volume
void SetGeometryParameters(const G4LogicalVolume *crystallogic);
///set bending angle of the crystal planes/axes
///(default fBendingAngle=0 => straight crystal);
///only non-negative values! crystal is bent in the positive direction of x
void SetBendingAngle(G4double tetab, const G4LogicalVolume *crystallogic);
///fBendingAngle MAY BE NOT THE SAME AS THE BENDING ANGLE OF THE CRYSTAL VOLUME
///THE VOLUME OF A BENT CRYSTAL MAY BE G4Box, while the planes/axes inside may be bent
///set miscut angle (default fMiscutAngle=0), acceptable range +-1 mrad,
///otherwise geometry routines may be unstable
void SetMiscutAngle(G4double tetam, const G4LogicalVolume *crystallogic);
///recalculate all the important values
///(to do both at the trajectory start and after energy loss)
void SetParticleProperties(G4double etotal,
G4double mp,
G4double charge,
G4bool ifhadron);
///calculate the coordinates in the co-rotating reference system
///within a channel (periodic cell)
///(connected with crystal planes/axes either bent or straight)
virtual G4ThreeVector CoordinatesFromBoxToLattice(const G4ThreeVector &pos0) = 0;
///calculate the coordinates in the Box reference system
///(connected with the bounding box of the volume)
virtual G4ThreeVector CoordinatesFromLatticeToBox(const G4ThreeVector &pos) = 0;
///change the channel if necessary, recalculate x o y
virtual G4ThreeVector ChannelChange(G4double& x, G4double& y,
G4double& z) = 0;
///return correction of the longitudinal coordinate
/// (along current plane/axis vs "central plane/axis")
G4double GetCorrectionZ(){return fCorrectionZ;}
///calculate the horizontal angle in the co-rotating reference system
///within a channel (periodic cell)
///(connected with crystal planes/axes either bent or straight)
virtual G4double AngleXFromBoxToLattice(G4double tx, G4double z)=0;
///calculate the horizontal angle in the Box reference system
///(connected with the bounding box of the volume)
virtual G4double AngleXFromLatticeToBox(G4double tx, G4double z)=0;
///auxialiary function to transform the horizontal angle
virtual G4double AngleXShift(G4double z)=0;
///multiple and single scattering on screened potential
G4ThreeVector CoulombAtomicScattering(
G4double effectiveStep,
G4double step,
G4int ielement);
///multiple and single scattering on electrons
G4ThreeVector CoulombElectronScattering(G4double eMinIonization,
G4double electronDensity,
G4double step);
///ionization losses
G4double IonizationLosses(G4double dz, G4int ielement);
void SetVerbosity(G4int ver){fVerbosity = ver;}
protected:
///classes containing interpolation coefficients
//horizontal electric field data
G4ChannelingFastSimInterpolation* fElectricFieldX{nullptr};
//vertical electric field data
G4ChannelingFastSimInterpolation* fElectricFieldY{nullptr};
//electron density data
G4ChannelingFastSimInterpolation* fElectronDensity{nullptr};
//minimal energy of ionization data
G4ChannelingFastSimInterpolation* fMinIonizationEnergy{nullptr};
//nuclear density distributions data
std::vector <G4ChannelingFastSimInterpolation*> fNucleiDensity;
///values related to the crystal geometry
G4ThreeVector fHalfDimBoundingBox;//bounding box half dimensions
G4int fBent=0;//flag of bent crystal,
//=0 for straight and =1 for bent, by default straight crystal
G4double fBendingAngle=0.;// angle of bending of the crystal planes/axes
//inside the crystal volume
//MAY BE NOT THE SAME AS THE BENDING ANGLE OF THE CRYSTAL VOLUME
//THE VOLUME OF A BENT CRYSTAL MAY BE G4Box,
//while the planes/axes inside may be bent
G4double fBendingR = 0.; // bending radius of the crystal planes/axes
G4double fBending2R=0.; // =2*fBendingR
G4double fBendingRsquare=0.; // =fBendingR**2
G4double fCurv=0.; //=1/fBendingR bending curvature of the crystal planes/axes
G4double fMiscutAngle = 0.;// miscut angle, can be of either sign or 0;
//safe values |ThetaMiscut|<0.001
G4double fCosMiscutAngle=1.;// = std::cos(fMiscutAngle), to economy operations
G4double fSinMiscutAngle=0.;// = std::sin(fMiscutAngle), to economy operations
G4double fCorrectionZ = 1.;//correction of the longitudinal coordinate
//(along current plane/axis vs "central plane/axis"), 1 is default value
//(for "central plane/axis" or a straight crystal)
///values related to the crystal lattice
G4int fNelements=1;//number of nuclear elements in a crystal
G4int iModel=1;// model type (iModel=1 for interplanar potential,
//iModel=2 for the interaxial one)
G4double fVmax=0; // the height of the potential well
G4double fVmax2=0; // =2*fVmax
G4double fVMinCrystal=0;// non-zero minimal potential inside the crystal,
// necessary for angle recalculation for entrance/exit
//through the crystal lateral surface
G4double fChangeStep=0;// fChannelingStep = fChangeStep/fTetaL
std::vector <G4double> fI0; //Mean excitation energy
std::vector <G4double> fRF;//Thomas-Fermi screening radius
///angles necessary for multiple and single coulomb scattering
//minimal scattering angle by coulomb scattering on nuclei
//defined by shielding by electrons
std::vector <G4double> fTeta10;//(in the Channeling model
//teta1=fTeta10/fPz*(1.13+fK40/vz**2)
//maximal scattering angle by coulomb scattering on nuclei defined by nucleus radius
std::vector <G4double> fTetamax0;//(in the Channeling model tetamax=fTetamax0/fPz)
std::vector <G4double> fTetamax2;//=tetamax*tetamax
std::vector <G4double> fTetamax12;//=teta1*teta1+tetamax*tetamax
std::vector <G4double> fTeta12; //= teta1*teta1
///coefficients necessary for multiple and single coulomb scattering
std::vector <G4double> fK20; //a useful coefficient, fK2=fK20/fPV/fPV
std::vector <G4double> fK2; //a useful coefficient,
//fK2=(fZ2*alpha*hdc)**2*4.*pi*fN0*(fZ1/fPV)**2
std::vector <G4double> fK40; //a useful coefficient, fK40=3.76D0*(alpha*fZ1)**2
G4double fK30=0;//a useful coefficient, fK3=fK30/fPV/fPV
G4double fK3=0;//a useful coefficient, fK3=2.*pi*alpha*hdc/electron_mass_c2/(fPV)**2
std::vector <G4double> fKD; //a useful coefficient for dE/dx
///coefficients for multiple scattering suppression
std::vector <G4double> fPu11;//a useful coefficient for exponent containing u1
std::vector <G4double> fPzu11;//a useful coefficient for exponent containing u1
std::vector <G4double> fBB;//a useful coefficient
std::vector <G4double> fE1XBbb;//a useful coefficient
std::vector <G4double> fBBDEXP;//a useful coefficient
//Variable to control printout
G4int fVerbosity = 1;
private:
//exponential integral
G4double expint(G4double x);
///private variables
std::unordered_map<G4int, G4double> fMapBendingAngle;//the map fBendingAngle
//for different logical volumes
std::unordered_map<G4int, G4double> fMapMiscutAngle;//the map fMiscutAngle
//for different logical volumes
G4double fChannelingStep=0;// simulation step under the channeling conditions =
//channeling oscillation length/fNsteps
// channeling oscillation length: Biryukov book Eq. (1.24)
///energy depended values
G4double fPz=0; // particle momentum absolute value
G4double fPV=0; // pv
G4double fTetaL=0; //Lindhard angle
G4double fBeta=0; //particle (velocity/c)
G4double fV2=0; // particle (velocity/c)^2
G4double fGamma=0; //Lorentz factor
G4double fMe2Gamma=0; // me^2*fGamma
G4double fTmax=0; // max ionization losses
///particle properties flags
G4bool fHadron=false;//=true (for hadrons); =false (for leptons)
G4double fZ2=0; //particle charge
};
#endif
@@ -0,0 +1,29 @@
# - G4channeling module build definition
# Define the Geant4 Module.
geant4_add_module(G4channeling
PUBLIC_HEADERS
G4BaierKatkov.hh
G4ChannelingFastSimCrystalData.hh
G4ChannelingFastSimInterpolation.hh
G4ChannelingFastSimModel.hh
G4VChannelingFastSimCrystalData.hh
SOURCES
G4BaierKatkov.cc
G4ChannelingFastSimCrystalData.cc
G4ChannelingFastSimInterpolation.cc
G4ChannelingFastSimModel.cc
G4VChannelingFastSimCrystalData.cc)
geant4_module_link_libraries(G4channeling
PUBLIC
G4geometrymng
G4globman
G4heprandom
G4materials
G4parameterisation
G4track
G4partman
PRIVATE
G4bosons
G4navigation)
@@ -0,0 +1,583 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4BaierKatkov.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
G4BaierKatkov::G4BaierKatkov()
{
//sets the default spectrum energy range of integration and
//calls ResetRadIntegral()
SetSpectrumEnergyRange(0.1*MeV,1.*GeV,110);
//Do not worry if the maximal energy > particle energy
//this elements of spectrum with non-physical energies
//will not be processed (they will be 0)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BaierKatkov::ResetRadIntegral()
{
fAccumSpectrum.clear();
//reinitialize intermediate integrals with zeros
fFa.resize(fNMCPhotons);
fSs.resize(fNMCPhotons);
fSc.resize(fNMCPhotons);
fSsx.resize(fNMCPhotons);
fSsy.resize(fNMCPhotons);
fScx.resize(fNMCPhotons);
fScy.resize(fNMCPhotons);
std::fill(fFa.begin(), fFa.end(), 0.);
std::fill(fSs.begin(), fSs.end(), 0.);
std::fill(fSc.begin(), fSc.end(), 0.);
std::fill(fSsx.begin(), fSsx.end(), 0.);
std::fill(fSsy.begin(), fSsy.end(), 0.);
std::fill(fScx.begin(), fScx.end(), 0.);
std::fill(fScy.begin(), fScy.end(), 0.);
//Reset radiation integral internal variables to defaults
fMeanPhotonAngleX =0.; //average angle of
//radiated photon direction in sampling, x-plane
fParamPhotonAngleX=1.e-3*rad; //a parameter of
//radiated photon sampling distribution, x-plane
fMeanPhotonAngleY =0.; //average angle of
//radiated photon direction in sampling, y-plane
fParamPhotonAngleY=1.e-3*rad; //a parameter of
//radiated photon sampling distribution, y-plane
fImin0 = 0;//set the first vector element to 0
//reset the trajectory
fParticleAnglesX.clear();
fParticleAnglesY.clear();
fScatteringAnglesX.clear();
fScatteringAnglesY.clear();
fSteps.clear();
fGlobalTimes.clear();
fParticleCoordinatesXYZ.clear();
//resets the vector of element numbers at the trajectory start
fImax0.clear();
//sets 0 element of the vector of element numbers
fImax0.push_back(0.);
//resets the radiation probability
fTotalRadiationProbabilityAlongTrajectory.clear();
//sets the radiation probability at the trajectory start
fTotalRadiationProbabilityAlongTrajectory.push_back(0.);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BaierKatkov::SetSpectrumEnergyRange(G4double emin,
G4double emax,
G4int numberOfBins)
{
fMinPhotonEnergy = emin;
fMaxPhotonEnergy = emax;
fNBinsSpectrum = numberOfBins;
fLogEmaxdEmin = std::log(fMaxPhotonEnergy/fMinPhotonEnergy);
//in initializing fNPhotonsPerBin
fNPhotonsPerBin.resize(fNBinsSpectrum);
std::fill(fNPhotonsPerBin.begin(), fNPhotonsPerBin.end(), 0);
//initializing the Spectrum
fSpectrum.resize(fNBinsSpectrum);
std::fill(fSpectrum.begin(), fSpectrum.end(), 0);
//initializing the fAccumTotalSpectrum
fAccumTotalSpectrum.resize(fNBinsSpectrum);
std::fill(fAccumTotalSpectrum.begin(), fAccumTotalSpectrum.end(), 0);
//initializing the fTotalSpectrum
fTotalSpectrum.resize(fNBinsSpectrum);
std::fill(fTotalSpectrum.begin(), fTotalSpectrum.end(), 0);
fPhotonEnergyInSpectrum.clear();
for (G4int j=0;j<fNBinsSpectrum;j++)
{
//bin position (mean between 2 bin limits)
fPhotonEnergyInSpectrum.push_back(fMinPhotonEnergy*
(std::exp(fLogEmaxdEmin*j/fNBinsSpectrum)+
std::exp(fLogEmaxdEmin*(j+1)/fNBinsSpectrum))/2.);
}
fItrajectories = 0;
ResetRadIntegral();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BaierKatkov::SetPhotonSamplingParameters(G4double ekin,
G4double minPhotonAngleX,
G4double maxPhotonAngleX,
G4double minPhotonAngleY,
G4double maxPhotonAngleY)
{
fLogEdEmin = std::log(ekin/fMinPhotonEnergy);
fMeanPhotonAngleX = (maxPhotonAngleX+minPhotonAngleX)/2.;
fParamPhotonAngleX = (maxPhotonAngleX-minPhotonAngleX)/2.;
fMeanPhotonAngleY = (maxPhotonAngleY+minPhotonAngleY)/2.;
fParamPhotonAngleY = (maxPhotonAngleY-minPhotonAngleY)/2.;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BaierKatkov::GeneratePhotonSampling()
{
fPhotonEnergyInIntegral.clear();
fPhotonAngleInIntegralX.clear();
fPhotonAngleInIntegralY.clear();
fPhotonAngleNormCoef.clear();
fIBinsSpectrum.clear();
G4double ksi=0.;
G4double rho=1.;
G4double rhocut=15.;//radial angular cut of the distribution
G4double norm=std::atan(rhocut*rhocut)*
CLHEP::pi*fParamPhotonAngleX*fParamPhotonAngleY;
//sampling of the energy and the angles of a photon emission
//(integration variables, Monte Carlo integration)
for (G4int j=0;j<fNMCPhotons;j++)
{
ksi = G4UniformRand();
fIBinsSpectrum.push_back((G4int)std::trunc(
ksi*fNBinsSpectrum*fLogEdEmin/fLogEmaxdEmin));
//we consider also the energy outside the spectrum output range
//(E>Emax => fLogEdEmin>fLogEmaxdEmin)
//in this case we don't count the photon in the spectrum output
if(fIBinsSpectrum[j]<fNBinsSpectrum) {fNPhotonsPerBin[fIBinsSpectrum[j]]+=1;}
fPhotonEnergyInIntegral.push_back(fMinPhotonEnergy*std::exp(fLogEdEmin*ksi));
//photon distribution with long tails (useful to not exclude particle angles
//after a strong single scattering)
//at ellipsescale < 1 => half of statistics of photons
do
{
rho = std::sqrt(std::tan(CLHEP::halfpi*G4UniformRand()));
}
while (rho>rhocut);
ksi = G4UniformRand();
fPhotonAngleInIntegralX.push_back(fMeanPhotonAngleX+
fParamPhotonAngleX*
rho*std::cos(CLHEP::twopi*ksi));
fPhotonAngleInIntegralY.push_back(fMeanPhotonAngleY+
fParamPhotonAngleY*
rho*std::sin(CLHEP::twopi*ksi));
fPhotonAngleNormCoef.push_back((1.+rho*rho*rho*rho)*norm);
}
//reinitialize the vector of radiation CDF for each photon
fPhotonProductionCDF.resize(fNMCPhotons+1);// 0 element is equal to 0
std::fill(fPhotonProductionCDF.begin(), fPhotonProductionCDF.end(), 0.);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4BaierKatkov::RadIntegral(G4double etotal, G4double mass,
std::vector<G4double> &vectorParticleAnglesX,
std::vector<G4double> &vectorParticleAnglesY,
std::vector<G4double> &vectorScatteringAnglesX,
std::vector<G4double> &vectorScatteringAnglesY,
std::vector<G4double> &vectorSteps,
G4int imin)
{
//preliminary values are defined:
G4double om=0.;// photon energy
G4double eprime=0., eprime2=0.; //E'=E-omega eprime2=eprime*eprime
G4double omprime=0.,omprimed2=0.;//om'=(E*om/E'), omprimed2=omprime/2
G4double vxin =0.,vyin=0.,vxno=0.,vyno=0.;
G4double dzmod=0.;
G4double fa1=0.,faseBefore=0.,faseBeforedz=0.,faseBeforedzd2=0.;
G4double faseAfter=0.,fa2dfaseBefore2=0.;
G4double skJ=0, skIx=0., skIy=0.;
G4double sinfa1=0.,cosfa1=0.;
G4double i2=0.,j2=0.;// Ix^2+Iy^2 and of BK Jvector^2
std::size_t nparts=vectorParticleAnglesX.size();
G4int kmin = imin;
if(imin==0) {kmin=1;}//skipping 0 trajectory element
//total radiation probability for each photon
G4double totalRadiationProbabilityPhj = 0.;
//total radiation probability along this trajectory (fill with 0 only new elements)
fTotalRadiationProbabilityAlongTrajectory.resize(nparts);
//reset Spectrum
std::fill(fSpectrum.begin(), fSpectrum.end(), 0.);
//intermediate vectors to reduce calculations
std::vector<G4double> axt;//acceleration of a charged particle in a horizontal plane
axt.resize(nparts);
std::vector<G4double> ayt;//acceleration of a charged particle in a vertical plane
ayt.resize(nparts);
std::vector<G4double> dz;//step in in MeV^-1
dz.resize(nparts);
//setting values interesting for us
for(std::size_t k=kmin;k<nparts;k++)
{
dz[k]=vectorSteps[k]/CLHEP::hbarc;// dz in MeV^-1
// accelerations
axt[k]=(vectorParticleAnglesX[k]-vectorScatteringAnglesX[k]-
vectorParticleAnglesX[k-1])/dz[k];
ayt[k]=(vectorParticleAnglesY[k]-vectorScatteringAnglesY[k]-
vectorParticleAnglesY[k-1])/dz[k];
}
//intermediate variables to reduce calculations:
//the calculations inside for (G4int j=0;j<fNMCPhotons;j++)
//{for(G4int k=kmin;k<nparts;k++){...
//are the main cpu time consumption
G4double e2 = etotal*etotal;
G4double gammaInverse2 = mass*mass/(etotal*etotal);// 1/gamma^2 of
//the radiating charge particle
G4double coefNormLogdNMC = fLogEdEmin/fNMCPhotons;
G4double coefNorm = CLHEP::fine_structure_const/(8*(CLHEP::pi2))*coefNormLogdNMC;
G4double e2pluseprime2 = 0.;//e2pluseprime2 =e2+eprime2
G4double coefNormom2deprime2 = 0.; //coefNormom2deprime2 = coefNorm*om2/eprime2;
G4double gammaInverse2om = 0.; //gammaInverse2*om
for (G4int j=0;j<fNMCPhotons;j++)
{
om = fPhotonEnergyInIntegral[j];
eprime=etotal-om; //E'=E-omega
eprime2 = eprime*eprime;
e2pluseprime2 =e2+eprime2;
omprime=etotal*om/eprime;//om'=(E*om/E')
omprimed2=omprime/2;
coefNormom2deprime2 = coefNorm*om*om/eprime2;
gammaInverse2om = gammaInverse2*om;
for(std::size_t k=kmin;k<nparts;k++)
{
//the angles of a photon produced (with incoherent scattering)
vxin = vectorParticleAnglesX[k]-fPhotonAngleInIntegralX[j];
vyin = vectorParticleAnglesY[k]-fPhotonAngleInIntegralY[j];
//the angles of a photon produced (without incoherent scattering)
vxno = vxin-vectorScatteringAnglesX[k];
vyno = vyin-vectorScatteringAnglesY[k];
//phase difference before scattering
faseBefore=omprimed2*(gammaInverse2+vxno*vxno+vyno*vyno);//phi' t<ti//MeV
faseBeforedz = faseBefore*dz[k];
faseBeforedzd2 = faseBeforedz/2.;
fFa[j]+=faseBeforedz; //
fa1=fFa[j]-faseBeforedzd2;//
dzmod=2*std::sin(faseBeforedzd2)/faseBefore;//MeV^-1
//phi''/faseBefore^2
fa2dfaseBefore2 = omprime*(axt[k]*vxno+ayt[k]*vyno)/(faseBefore*faseBefore);
//phase difference after scattering
faseAfter=omprimed2*(gammaInverse2+vxin*vxin+vyin*vyin);//phi' ti+O//MeV
skJ=1/faseAfter-1/faseBefore-fa2dfaseBefore2*dzmod;//MeV^-1
skIx=vxin/faseAfter-vxno/faseBefore+dzmod*(axt[k]/faseBefore-
vxno*fa2dfaseBefore2);
skIy=vyin/faseAfter-vyno/faseBefore+dzmod*(ayt[k]/faseBefore-
vyno*fa2dfaseBefore2);
sinfa1 = std::sin(fa1);
cosfa1 = std::cos(fa1);
fSs[j]+=sinfa1*skJ;//sum sin integral J of BK
fSc[j]+=cosfa1*skJ;//sum cos integral J of BK
fSsx[j]+=sinfa1*skIx;// sum sin integral Ix of BK
fSsy[j]+=sinfa1*skIy;// sum sin integral Iy of BK
fScx[j]+=cosfa1*skIx;// sum cos integral Ix of BK
fScy[j]+=cosfa1*skIy;// sum cos integral Iy of BK
i2=fSsx[j]*fSsx[j]+fScx[j]*fScx[j]+fSsy[j]*fSsy[j]+fScy[j]*fScy[j];//MeV^-2
j2=fSs[j]*fSs[j]+fSc[j]*fSc[j];//MeV^-2
//updating the total radiation probability along the trajectory
totalRadiationProbabilityPhj = coefNormom2deprime2*fPhotonAngleNormCoef[j]*
(i2*e2pluseprime2+j2*gammaInverse2om);
fTotalRadiationProbabilityAlongTrajectory[k] += totalRadiationProbabilityPhj;
}
fPhotonProductionCDF[j+1] = fTotalRadiationProbabilityAlongTrajectory.back();
//filling spectrum (adding photon probabilities to a histogram)
//we consider also the energy outside the spectrum output range
//(E>Emax => fLogEdEmin>fLogEmaxdEmin)
//in this case we don't count the photon in the spectrum output
if(fIBinsSpectrum[j]<fNBinsSpectrum)
{fSpectrum[fIBinsSpectrum[j]] += totalRadiationProbabilityPhj/
(om*coefNormLogdNMC);}
} // end cycle
fAccumSpectrum.push_back(fSpectrum);
return fTotalRadiationProbabilityAlongTrajectory.back();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4BaierKatkov::FindVectorIndex(std::vector<G4double> &myvector, G4double value)
{
auto iteratorbegin = myvector.begin();
auto iteratorend = myvector.end();
//vector index (for non precise values lower_bound gives upper value)
auto loweriterator = std::lower_bound(iteratorbegin, iteratorend, value);
//return the index of the vector element
return (G4int)std::distance(iteratorbegin, loweriterator);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BaierKatkov::SetPhotonProductionParameters(G4double etotal, G4double mass)
{
//flag if a photon was produced
G4bool flagPhotonProduced = false;
//how many small pieces of a trajectory are
//before radiation (all if not radiation)
std::size_t nodeNumber = fAccumSpectrum.size()-1;
//ksi is a random number
//Generally ksi = G4UniformRand() is ok, but
//we use as a correction for the case
//when the radiation probability becomes too high (> 0.1)
G4double ksi = -std::log(G4UniformRand());
if (ksi< fTotalRadiationProbabilityAlongTrajectory.back()) // photon produced
{
//randomly choosing the photon to be produced from the sampling list
//according to the probabilities calculated in the Baier-Katkov integral
G4int iphoton = FindVectorIndex(fPhotonProductionCDF,ksi)-1;//index of
//a photon produced
//energy of the photon produced
fEph0 = fPhotonEnergyInIntegral[iphoton];
//anagles of the photon produced
G4double photonAngleX = fPhotonAngleInIntegralX[iphoton];
G4double photonAngleY = fPhotonAngleInIntegralY[iphoton];
G4double momentumDirectionZ = 1./
std::sqrt(1.+std::pow(std::tan(photonAngleX),2)+
std::pow(std::tan(photonAngleY),2));
//momentum direction vector of the photon produced
PhMomentumDirection.set(momentumDirectionZ*std::tan(photonAngleX),
momentumDirectionZ*std::tan(photonAngleY),
momentumDirectionZ);
//random calculation of the radiation point index (iNode)
ksi = G4UniformRand()*fTotalRadiationProbabilityAlongTrajectory.back();
//sort fTotalRadiationProbabilityAlongTrajectory
//(increasing but oscillating function => non-monotonic)
std::vector<G4double> temporaryVector;
temporaryVector.assign(fTotalRadiationProbabilityAlongTrajectory.begin(),
fTotalRadiationProbabilityAlongTrajectory.end());
std::sort(temporaryVector.begin(), temporaryVector.end());
//index of the point of radiation ("poststep") in sorted vector
G4int iNode = FindVectorIndex(temporaryVector,ksi);
//index of the point of radiation ("poststep") in unsorted vector
auto it = std::find_if(fTotalRadiationProbabilityAlongTrajectory.begin(),
fTotalRadiationProbabilityAlongTrajectory.end(),
[&](G4double value)
{return std::abs(value - temporaryVector[iNode]) < DBL_EPSILON;});
iNode = (G4int)std::distance(fTotalRadiationProbabilityAlongTrajectory.begin(), it);
//the piece of trajectory number (necessary only for the spectrum output)
nodeNumber = FindVectorIndex(fImax0,iNode*1.)-1;
//set new parameters of the charged particle
//(returning the particle back to the radiation point, i.e.
//remembering the new parameters for corresponding get functions)
fNewParticleEnergy = etotal-fEph0;
fNewParticleAngleX = fParticleAnglesX[iNode];
fNewParticleAngleY = fParticleAnglesY[iNode];
fNewGlobalTime = fGlobalTimes[iNode];
fNewParticleCoordinateXYZ = fParticleCoordinatesXYZ[iNode];
//particle angle correction from momentum conservation
//(important for fEph0 comparable to E,
// may kick off a particle from channeling)
G4double pratio = fEph0/std::sqrt(etotal*etotal-mass*mass);
fNewParticleAngleX -= std::asin(pratio*std::sin(photonAngleX));
fNewParticleAngleY -= std::asin(pratio*std::sin(photonAngleY));
flagPhotonProduced = true;
}
//accumulation during entire code run
for (G4int j=0;j<fNBinsSpectrum;j++)
{
fAccumTotalSpectrum[j] += fAccumSpectrum[nodeNumber][j];
//in the case of missing photon in spectrum, probability is 0
//(may happen only at the beginning of simulations)
if(fNPhotonsPerBin[j]==0)
{
fTotalSpectrum[j] = 0;
}
else
{
fTotalSpectrum[j] = fAccumTotalSpectrum[j]/fNPhotonsPerBin[j]*fItrajectories;
}
}
return flagPhotonProduced;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4BaierKatkov::DoRadiation(G4double etotal, G4double mass,
G4double angleX, G4double angleY,
G4double angleScatteringX, G4double angleScatteringY,
G4double step, G4double globalTime,
G4ThreeVector coordinateXYZ,
G4bool flagEndTrajectory)
{
/**
DoRadiation description
The real trajectory is divided onto parts.
Every part is accumulated until the radiation cannot be considered as single photon,
i.e. the radiation probability exceeds some threshold
fSinglePhotonRadiationProbabilityLimit.
Typically fSinglePhotonRadiationProbabilityLimit should be between 0.01 and 0.1.
Then the photon generation as well as its parameters are simulated
in SetPhotonProductionParameters()
Finally if radiation took place, this function sets the new particle parameters
(the parameters at the point of radiation emission)
fNewParticleEnergy; fNewParticleAngleX;
fNewParticleAngleY; NewStep; fNewGlobalTime; fNewParticleCoordinateXYZ;
In order to control if the trajectory part reaches this limit,
one needs to divide it into smaller pieces (consisting of
fNSmallTrajectorySteps elements, typically several hundred) and to calculate the total
radiation probability along the trajectory part after each small piece accomplished.
If it exceeds the fSinglePhotonRadiationProbabilityLimit,
the trajectory part is over and the radiation can be generated.
In order to calculate the radiation probability the Baier-Katkov integral is called
after each small piece of the trajectory. It is summarized with the integral along
the previous small pieces for this part of the trajectory.
To speed-up the simulations, the photon angles are generated only once
at the start of the trajectory part.
*/
//flag if a photon was produced
G4bool flagPhotonProduced = false;
//adding the next trajectory element to the vectors
fParticleAnglesX.push_back(angleX);
fParticleAnglesY.push_back(angleY);
fScatteringAnglesX.push_back(angleScatteringX);
fScatteringAnglesY.push_back(angleScatteringY);
fSteps.push_back(step);
fGlobalTimes.push_back(globalTime);
fParticleCoordinatesXYZ.push_back(coordinateXYZ);
G4double imax = fSteps.size();
if((imax==fImin0+fNSmallTrajectorySteps)||flagEndTrajectory)
{
//set the angular limits at the start of the trajectory part
if(fImin0==0)
{
//radiation within the angle = +-4/gamma ("4" - just an empirical number)
G4double radiationAngleLimit=4*mass/etotal;
SetPhotonSamplingParameters(etotal-mass,
*std::min_element(fParticleAnglesX.begin(),
fParticleAnglesX.end())-radiationAngleLimit,
*std::max_element(fParticleAnglesX.begin(),
fParticleAnglesX.end())+radiationAngleLimit,
*std::min_element(fParticleAnglesY.begin(),
fParticleAnglesY.end())-radiationAngleLimit,
*std::max_element(fParticleAnglesY.begin(),
fParticleAnglesY.end())+radiationAngleLimit);
//calculation of angles of photon emission
//(these angles are integration variables, Monte Carlo integration)
GeneratePhotonSampling();
}
//calculate Baier-Katkov integral after this
//small piece of trajectory (fNSmallTrajectorySteps elements)
fTotalRadiationProbability = RadIntegral(etotal,mass,
fParticleAnglesX,fParticleAnglesY,
fScatteringAnglesX,fScatteringAnglesY,
fSteps, fImin0);
//setting the last element of this small trajectory piece
fImin0 = imax;
fImax0.push_back(imax*1.);
//if the radiation probability is high enough or if we are finishing
//our trajectory => to simulate the photon emission
if(fTotalRadiationProbability>fSinglePhotonRadiationProbabilityLimit||
flagEndTrajectory)
{
flagPhotonProduced = SetPhotonProductionParameters(etotal,mass);
fItrajectories += 1; //count this trajectory
//reinitialize intermediate integrals fFa, fSs, fSc, fSsx, fSsy, fScx, fScy;
//reset radiation integral internal variables to defaults;
//reset the trajectory and radiation probability along the trajectory
ResetRadIntegral();
}
}
return flagPhotonProduced;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BaierKatkov::GeneratePhoton(G4FastStep &fastStep)
{
const G4DynamicParticle theGamma = G4DynamicParticle(G4Gamma::Gamma(),
PhMomentumDirection,fEph0);
//generation of a secondary photon
fastStep.CreateSecondaryTrack(theGamma,fNewParticleCoordinateXYZ,fNewGlobalTime,true);
}
@@ -0,0 +1,408 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4ChannelingFastSimCrystalData.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
G4ChannelingFastSimCrystalData::G4ChannelingFastSimCrystalData()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ChannelingFastSimCrystalData::SetMaterialProperties(const G4Material *crystal,
const G4String &lattice)
{
G4String filename=crystal->GetName(); //input file
filename.erase(0,3);
if (fVerbosity)
{
G4cout <<
"======================================================================="
<< G4endl;
G4cout <<
"====== Crystal lattice data ========"
<< G4endl;
G4cout <<
"======================================================================="
<< G4endl;
G4cout << "Crystal material: " << filename << G4endl;
}
//choice between planes (1D model) and axes (2D model)
if (lattice.compare(0,1,"(")==0)
{
iModel=1; //planes
filename = filename + "_planes_"; //temporary name
if (fVerbosity)
G4cout << "Crystal planes: " << lattice << G4endl;
}
else if (lattice.compare(0,1,"<")==0)
{
iModel=2; //axes
filename = filename + "_axes_"; //temporary name
if (fVerbosity)
G4cout << "Crystal axes: " << lattice << G4endl;
}
//input file:
filename = filename + lattice.substr(1,(lattice.length())-2) + ".dat";
fNelements=(G4int)crystal->GetNumberOfElements();
for(G4int i=0; i<fNelements; i++)
{
fZ1.push_back(crystal->GetElement(i)->GetZ());
fAN.push_back(crystal->GetElement(i)->GetAtomicMassAmu());
fI0.push_back(crystal->GetElement(i)->GetIonisation()->GetMeanExcitationEnergy());
}
G4double var;//just variable
G4double unitIF;//unit of interpolation function
std::ifstream vfilein;
vfilein.open(filename);
//read nuclear concentration
for(G4int i=0; i<fNelements; i++)
{
vfilein >> var;
fN0.push_back(var/cm3);
}
//read amplitude of thermal oscillations
for(G4int i=0; i<fNelements; i++)
{
vfilein >> var;
fU1.push_back(var*cm);
}
if (iModel==1)
{
// read channel dimensions
vfilein >> fDx;
fDx*=cm;
// read interpolation step size
vfilein >> fNpointsx;
fDy = fDx;
fNpointsy = 0;
}
else if (iModel==2)
{
// read channel dimensions
vfilein >> fDx >> fDy;
fDx*=cm;
fDy*=cm;
// read the number of nodes of interpolation
vfilein >> fNpointsx >> fNpointsy;
}
//read the height of the potential well, necessary only for step length calculation
vfilein >> fVmax;
fVmax*=eV;
fVmax2=2.*fVmax;
//read the on-zero minimal potential inside the crystal,
//necessary for angle recalculation for entrance/exit through the crystal lateral surface
vfilein >> fVMinCrystal;
fVMinCrystal*=eV;
// to create the class of interpolation for any function
fElectricFieldX =
new G4ChannelingFastSimInterpolation(fDx,fDy,fNpointsx,fNpointsy,iModel);
if(iModel==2) {fElectricFieldY =
new G4ChannelingFastSimInterpolation(fDx,fDy,fNpointsx,fNpointsy,iModel);}
fElectronDensity =
new G4ChannelingFastSimInterpolation(fDx,fDy,fNpointsx,fNpointsy,iModel);
fMinIonizationEnergy =
new G4ChannelingFastSimInterpolation(fDx,fDy,fNpointsx,fNpointsy,iModel);
// do it for any element of crystal material
for(G4int i=0; i<fNelements; i++)
{
fNucleiDensity.push_back(
new G4ChannelingFastSimInterpolation(fDx,fDy,fNpointsx,fNpointsy,iModel));
}
if (iModel==1)
{
G4double ai, bi, ci, di;
for(G4int i=0; i<fNpointsx; i++)
{
//reading the coefficients of cubic spline
vfilein >> ai >> bi >> ci >> di;
//setting spline coefficients for electric field
unitIF=eV/cm;
fElectricFieldX->SetCoefficients1D(ai*unitIF, bi*unitIF,
ci*unitIF, di*unitIF, i);
//reading the coefficients of cubic spline
vfilein >> ai >> bi >> ci >> di;
//setting spline coefficients for nuclear density (first element)
unitIF=1.;
fNucleiDensity[0]->SetCoefficients1D(ai*unitIF, bi*unitIF,
ci*unitIF, di*unitIF, i);
//reading the coefficients of cubic spline
vfilein >> ai >> bi >> ci >> di;
//setting spline coefficients for electron density
unitIF=1./cm3;
fElectronDensity->SetCoefficients1D(ai*unitIF, bi*unitIF,
ci*unitIF, di*unitIF, i);
//reading the coefficients of cubic spline
vfilein >> ai >> bi >> ci >> di;
//setting spline coefficients for minimal ionization energy
unitIF=eV;
fMinIonizationEnergy->SetCoefficients1D(ai*unitIF, bi*unitIF,
ci*unitIF, di*unitIF, i);
for(G4int ii=1; ii<fNelements; ii++)
{
//reading the coefficients of cubic spline
vfilein >> ai >> bi >> ci >> di;
//setting spline coefficients for nuclear density (other elements if any)
unitIF=1.;
fNucleiDensity[ii]->SetCoefficients1D(ai*unitIF, bi*unitIF,
ci*unitIF, di*unitIF, i);
}
}
}
else if (iModel==2)
{
G4double ai3D, bi3D, ci3D;
for(G4int j=0; j<fNpointsy; j++)
{
for(G4int i=0; i<fNpointsx+1; i++)
{
for(G4int k=0; k<2; k++)
{
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
unitIF=eV;
//setting spline coefficients for minimal ionization energy
fMinIonizationEnergy->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF, ci3D*unitIF,
i, j, k);
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
//setting spline coefficients for horizontal electric field
unitIF=eV/cm;
fElectricFieldX->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF, ci3D*unitIF,
i, j, k);
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
//setting spline coefficients for vertical electric field
unitIF=eV/cm;
fElectricFieldY->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF, ci3D*unitIF,
i, j, k);
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
//setting spline coefficients for nuclear density (first element)
unitIF=1.;
fNucleiDensity[0]->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF, ci3D*unitIF,
i, j, k);
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
//setting spline coefficients for electron density
unitIF=1./cm3;
fElectronDensity->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF, ci3D*unitIF,
i, j, k);
for(G4int ii=1; ii<fNelements; ii++)
{
//reading the coefficients of cubic spline
vfilein >> ai3D >> bi3D >> ci3D;
//setting spline coefficients for nuclear density (other elements if any)
unitIF=1.;
fNucleiDensity[ii]->SetCoefficients2D(ai3D*unitIF, bi3D*unitIF,
ci3D*unitIF,
i, j, k);
}
}
}
}
}
vfilein.close();
//set special values and coefficients
G4double alphahbarc2=std::pow(CLHEP::fine_structure_const*CLHEP::hbarc ,2.);
fK30=2.*CLHEP::pi*alphahbarc2/CLHEP::electron_mass_c2;
for(G4int i=0; i<fNelements; i++)
{
fRF.push_back((std::pow(9*CLHEP::pi*CLHEP::pi/128/fZ1[i],1/3.))
*0.5291772109217*angstrom);//Thomas-Fermi screening radius
fTetamax0.push_back(CLHEP::hbarc/(fR0*std::pow(fAN[i],1./3.)));
fTeta10.push_back(CLHEP::hbarc/fRF[i]);
fPu11.push_back(std::pow(fU1[i]/CLHEP::hbarc,2.));
fK20.push_back(alphahbarc2*4*CLHEP::pi*fN0[i]*fZ1[i]*fZ1[i]);
fK40.push_back(3.76*std::pow(CLHEP::fine_structure_const*fZ1[i],2.));
fKD.push_back(fK30*fZ1[i]*fN0[i]);
}
fBB.resize(fNelements);
fE1XBbb.resize(fNelements);
fBBDEXP.resize(fNelements);
fPzu11.resize(fNelements);
fTeta12.resize(fNelements);
fTetamax2.resize(fNelements);
fTetamax12.resize(fNelements);
fK2.resize(fNelements);
fChangeStep = CLHEP::pi*std::min(fDx,fDy)/fNsteps;//necessary to define simulation
//step = fChannelingStep =
// = fChannelingStep0*sqrt(pv)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4ChannelingFastSimCrystalData::CoordinatesFromBoxToLattice
(const G4ThreeVector &pos0)
{
G4double x0=pos0.x(),y0=pos0.y(),z0=pos0.z();
z0+=fHalfDimBoundingBox.z();
G4double x,y,z;
if (fBent)
{
// for bent crystal
G4double rsqrt = std::sqrt(fBendingRsquare -
fBending2R*(x0*fCosMiscutAngle - z0*fSinMiscutAngle) +
x0*x0 + z0*z0);
//transform to co-rotating reference system connected with "central plane/axis"
x = fBendingR - rsqrt;
y = y0;
z = fBendingR*std::asin((z0*fCosMiscutAngle + x0*fSinMiscutAngle)/rsqrt);
}
else
{
//for straight crystal
x = x0*fCosMiscutAngle - z0*fSinMiscutAngle;
y = y0;
z = x0*fSinMiscutAngle + z0*fCosMiscutAngle;
}
//calculation of coordinates within a channel (periodic cell)
fNChannelx=std::floor(x/fDx); //remember the horizontal channel number
//to track the particle
x-=fNChannelx*fDx;
fNChannely=std::floor(y/fDy);//remember the vertical channel number
//to track the particle (=0 for planar case)
y-=fNChannely*fDy;
//correction of the longitudinal coordinate
if (fBent) {fCorrectionZ = fBendingR/(fBendingR-fNChannelx*fDx);}
return G4ThreeVector(x,y,z);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4ChannelingFastSimCrystalData::CoordinatesFromLatticeToBox(
const G4ThreeVector &pos)
{
G4double x=pos.x(),y=pos.y(),z=pos.z();
//transform to co-rotating reference system connected with "central plane/axis"
x+=fNChannelx*fDx;
y+=fNChannely*fDy;
G4double x0,y0,z0;
if (fBent)
{
// for bent crystal
G4double rcos = (fBendingR - x)*(1. - std::cos(z/fBendingR));
G4double a = x + rcos;
G4double b = std::sqrt(x*x + fBending2R*rcos - a*a);
//transform to Box coordinates
x0 = a*fCosMiscutAngle + b*fSinMiscutAngle;
y0 = y;
z0 = b*fCosMiscutAngle - a*fSinMiscutAngle;
}
else
{
//for straight crystal
x0 = x*fCosMiscutAngle + z*fSinMiscutAngle;
y0 = y;
z0 =-x*fSinMiscutAngle + z*fCosMiscutAngle;
}
return G4ThreeVector(x0,y0,z0-fHalfDimBoundingBox.z());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4ChannelingFastSimCrystalData::ChannelChange(G4double& x,
G4double& y,
G4double& z)
{
//test of enter in other channel
if (x<0)
{
fNChannelx-=1;
x+=fDx; //enter in other channel
//correction of the longitudinal coordinate
if (fBent) {fCorrectionZ = fBendingR/(fBendingR-fNChannelx*fDx);}
}
else if (x>=fDx)
{
fNChannelx+=1;
x-=fDx; //enter in other channel
//correction of the longitudinal coordinate
if (fBent) {fCorrectionZ = fBendingR/(fBendingR-fNChannelx*fDx);}
}
//test of enter in other channel
if (y<0)
{
fNChannely-=1;
y+=fDy; //enter in other channel
}
else if (y>=fDy)
{
fNChannely+=1;
y-=fDy; //enter in other channel
}
return G4ThreeVector(x,y,z);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,201 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file G4ChannelingFastSimInterpolation.cc
/// \brief Implementation of the G4ChannelingFastSimInterpolation class
#include "G4ChannelingFastSimInterpolation.hh"
#include "G4SystemOfUnits.hh"
G4ChannelingFastSimInterpolation::G4ChannelingFastSimInterpolation(G4double dx0,
G4double dy0,
G4int nPointsx0,
G4int nPointsy0,
G4int iModel0)
{
fDx = dx0;
fDy = dy0;
nPointsx = nPointsx0;
nPointsy = nPointsy0;
fStepi = fDx/nPointsx;
fStepi2= fStepi*fStepi;
iModel = iModel0;
//resize vectors for interpolation coefficients
if(iModel==1)
{
fAI.resize(nPointsx+1);
fBI.resize(nPointsx+1);
fCI.resize(nPointsx+1);
fDI.resize(nPointsx+1);
}
else if(iModel==2)
{
fStepj = fDy/nPointsy;
fAI3D.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
fBI3D.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
fCI3D.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
fAI3D3.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
fBI3D3.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
fCI3D3.resize(nPointsx+1, std::vector<G4double>(nPointsy+1));
for(G4int i=0; i<=nPointsx; i++)
{
fCI3D[i][nPointsy]=0.;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ChannelingFastSimInterpolation::GetIF(G4double xx, G4double yy){
G4double SplineF=0.;
if(iModel==1)
{
SplineF = Spline1D(xx);
}
else if(iModel==2)
{
SplineF = Spline2D(xx, yy);
}
return SplineF;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ChannelingFastSimInterpolation::SetCoefficients1D(G4double AI0,
G4double BI0,
G4double CI0,
G4double DI0,
G4int i){
fAI[i] = AI0;
fBI[i] = BI0/cm;
fCI[i] = CI0/cm2;
fDI[i] = DI0/cm3;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ChannelingFastSimInterpolation::SetCoefficients2D(G4double AI3D0,
G4double BI3D0,
G4double CI3D0,
G4int i,
G4int j,
G4int k){
if (k==0)
{
fAI3D[i][j] = AI3D0/fStepj/fStepi/6.;
fBI3D[i][j] = BI3D0/fStepj/fStepi/6.;
fCI3D[i][j] = CI3D0/fStepj/fStepi/6./cm2;
}
else if (k==1)
{
fAI3D3[i][j] = AI3D0/fStepj/fStepi/6./cm2;
fBI3D3[i][j] = BI3D0/fStepj/fStepi/6./cm2;
fCI3D3[i][j] = CI3D0/fStepj/fStepi/6./cm2/cm2;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ChannelingFastSimInterpolation::Spline1D(G4double xx) //cubic spline of
//1-variable function
{
G4double x1 = xx;
//if a particle escapes the interpolation area
if (x1<0.)
{
x1 += fDx;
}
else if (x1>=fDx)
{
x1 -= fDx;
}
// calculation of interpolation function
G4int mmx = std::floor(x1/fStepi);
x1 -= (mmx+1)*fStepi;
G4double Spline3 = fAI[mmx]+x1*(fBI[mmx]+x1*(fCI[mmx]+fDI[mmx]*x1));
return Spline3;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ChannelingFastSimInterpolation::Spline2D(G4double xx, G4double yy)//cubic
//spline of 2-variable function
{
G4double x1 = xx;
G4double y1 = yy;
//if a particle escapes the interpolation area
if (x1<0.)
{
x1 += fDx;
}
else if (x1>=fDx)
{
x1 -= fDx;
}
if (y1<0.)
{
y1 += fDy;
}
else if (y1>=fDy)
{
y1 -= fDy;
}
// calculation of interpolation function
G4int mmx = std::floor(x1/fStepi);
G4int mmy = std::floor(y1/fStepj);
G4double tt1 = x1-mmx*fStepi;
G4double tt2 = fStepi-tt1;
G4double tt13 = tt1*tt1*tt1;
G4double tt23 = tt2*tt2*tt2;
G4double tt1y = y1-mmy*fStepj;
G4double tt2y = fStepj-tt1y;
G4double tt1y3 = tt1y*tt1y*tt1y;
G4double tt2y3 = tt2y*tt2y*tt2y;
G4double spl3dxx1 = fCI3D3[mmx ][mmy]*tt2y3 + fCI3D3[mmx ][mmy+1]*tt1y3 +
fAI3D3[mmx ][mmy]*tt2y + fBI3D3[mmx ][mmy]*tt1y;
G4double spl3dxx2 = fCI3D3[mmx+1][mmy]*tt2y3 + fCI3D3[mmx+1][mmy+1]*tt1y3 +
fAI3D3[mmx+1][mmy]*tt2y + fBI3D3[mmx+1][mmy]*tt1y;
G4double spl3d1 = fCI3D[ mmx ][mmy]*tt2y3 + fCI3D[mmx ][mmy+1]*tt1y3 +
fAI3D[ mmx ][mmy]*tt2y + fBI3D[mmx ][mmy]*tt1y;
G4double spl3d2 = fCI3D[ mmx+1][mmy]*tt2y3 + fCI3D[mmx+1][mmy+1]*tt1y3 +
fAI3D[ mmx+1][mmy]*tt2y + fBI3D[mmx+1][mmy]*tt1y;
G4double spl3d = spl3dxx1*tt23 + spl3dxx2*tt13 +
(spl3d1*6.-spl3dxx1*fStepi2)*tt2 + (spl3d2*6.-spl3dxx2*fStepi2)*tt1;
return spl3d;
}
@@ -0,0 +1,505 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file B107FastSim/src/G4ChannelingFastSimModel.cc
/// \brief Implementation of the G4ChannelingFastSimModel class
//
//
//
#include "G4ChannelingFastSimModel.hh"
#include "Randomize.hh"
#include "G4TransportationManager.hh"
#include "G4SystemOfUnits.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ChannelingFastSimModel::G4ChannelingFastSimModel(const G4String& modelName, G4Region* envelope)
: G4VFastSimulationModel(modelName, envelope)
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ChannelingFastSimModel::G4ChannelingFastSimModel(const G4String& modelName)
: G4VFastSimulationModel(modelName)
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ChannelingFastSimModel::~G4ChannelingFastSimModel()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4ChannelingFastSimModel::IsApplicable(const G4ParticleDefinition& particleType)
{
return std::abs(particleType.GetPDGCharge())>DBL_EPSILON;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4ChannelingFastSimModel::ModelTrigger(const G4FastTrack& fastTrack)
{
//default output
G4bool modelTrigger = false;
G4int particleDefinitionID =
fastTrack.GetPrimaryTrack()->GetParticleDefinition()->GetParticleDefinitionID();
//kinetic energy
G4double ekinetic = fastTrack.GetPrimaryTrack()->GetKineticEnergy();
//energy cut, at the beginning, to not check everything else
if(ekinetic > GetLowKineticEnergyLimit(particleDefinitionID))
{
//current logical volume
G4LogicalVolume* crystallogic = fastTrack.GetEnvelopeLogicalVolume();
fCrystalData->SetGeometryParameters(crystallogic);
G4ThreeVector momentumDirection = fastTrack.GetPrimaryTrackLocalDirection();
// the particle angle vs crystal plane or axis
G4double angle = std::atan(momentumDirection.x()/momentumDirection.z());
//recalculate angle into the lattice reference system
angle = fCrystalData->
AngleXFromBoxToLattice(angle,
(fCrystalData->CoordinatesFromBoxToLattice(
fastTrack.GetPrimaryTrackLocalPosition())).z());
if (fCrystalData->GetModel()==2)
{
angle = std::sqrt(angle*angle+
std::pow(std::atan(momentumDirection.y()/
momentumDirection.z()),2));
}
//particle mass
G4double mass = fastTrack.GetPrimaryTrack()->GetParticleDefinition()->GetPDGMass();
//particle total energy
G4double etotal = fastTrack.GetPrimaryTrack()->GetTotalEnergy();
//Particle position
G4ThreeVector xyz0 = fastTrack.GetPrimaryTrackLocalPosition();
//Step estimate
G4double dz0 = fCrystalData->GetMaxSimulationStep(etotal,mass);
xyz0 += 2*dz0*momentumDirection;//overestimated particle shift on the next step
//in channeling
//Applies the parameterisation not at the last step, only forward local direction
//above low energy limit and below angular limit
modelTrigger = (crystallogic->GetSolid()->
Inside(xyz0)==kInside) &&
momentumDirection.z()>0. &&
std::abs(angle) < GetLindhardAngleNumberHighLimit(particleDefinitionID) *
fCrystalData->GetLindhardAngle(etotal,mass);
}
return modelTrigger;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4ChannelingFastSimModel::DoIt(const G4FastTrack& fastTrack,
G4FastStep& fastStep)
{
G4double etotal;//particle total energy
G4double etotalPreStep;//etotal at the previous step
G4double etotalToSetParticleProperties;//etotal value at which
//SetParticleProperties is called
G4double mass; //particle mass
G4double charge;//particle charge
G4double tGlobal; //global time
G4double tGlobalPreStep; //global time at the previous step
G4ThreeVector xyz0;// the coordinates in the local reference system of the volume
G4ThreeVector xyz0PreStep;// xyz at the previous step
G4ThreeVector xyz;// the coordinates in the co-rotating reference system within
//a channel (elementary periodic cell)
G4double x,y,z; // the coordinates in the co-rotating reference system within
//a channel (elementary periodic cell)
G4double tx0,ty0; // the angles in the local reference system of the volume
G4double tx,ty; // the angles in the co-rotating reference system within
//a channel (elementary periodic cell)
G4double txPreStep,tyPreStep;// tx,ty at the previous step
G4ThreeVector momentumDirection;
G4ThreeVector scatteringAnglesAndEnergyLoss;//output of scattering functions
G4double lindhardAngleNumberHighLimit0; //current high limit of the angle expressed in
//[Lindhard angle] units
//coordinates in Runge-Kutta calculations
G4double x1=0.,x2=0.,x3=0.,x4=0.,y1=0.,y2=0.,y3=0.,y4=0.;
//angles in Runge-Kutta calculations
G4double tx1=0.,tx2=0.,tx3=0.,tx4=0.,ty1=0.,ty2=0.,ty3=0.,ty4=0.;
//variables in Runge-Kutta calculations
G4double kvx1=0.,kvx2=0.,kvx3=0.,kvx4=0.,kvy1=0.,kvy2=0.,kvy3=0.,kvy4=0.;
//simulation step along z (internal step of the model) and its parts
G4double dz,dzd3,dzd8;//dzd3 = dz/3; dzd8 = dz/8;
//simulation step along the momentum direction
G4double momentumDirectionStep;
//effective simulation step (taking into account nuclear density along the trajectory)
G4double effectiveStep;
// flag, if Inside(xyz0) switches to kInside
G4bool inside = false;
G4LogicalVolume* crystallogic = fastTrack.GetEnvelopeLogicalVolume();
fCrystalData->SetGeometryParameters(crystallogic);
//set the max number of secondaries (photons) that can be added at this fastStep
if (fRad)
{
fastStep.SetNumberOfSecondaryTracks(fMaxPhotonsProducedPerStep);
//reseting the BaierKatkov integral to start it with the new trajectory
fBaierKatkov->ResetRadIntegral();//to avoid any memory from the previous trajectory
}
etotal = fastTrack.GetPrimaryTrack()->GetTotalEnergy();
mass = fastTrack.GetPrimaryTrack()->GetParticleDefinition()->GetPDGMass();
charge = fastTrack.GetPrimaryTrack()->GetParticleDefinition()->GetPDGCharge();
// we need to distunguish only charge particles, either leptons or hadrons
G4bool hadron =
fastTrack.GetPrimaryTrack()->GetParticleDefinition()->GetLeptonNumber()==0;
lindhardAngleNumberHighLimit0 =
GetLindhardAngleNumberHighLimit(fastTrack.GetPrimaryTrack()->
GetParticleDefinition()->GetParticleDefinitionID());
//set fCrystalData parameters depending on the particle parameters
fCrystalData->SetParticleProperties(etotal, mass, charge, hadron);
//global time
tGlobal = fastTrack.GetPrimaryTrack()->GetGlobalTime();
//coordinates in the co-rotating reference system within a channel
xyz0= fastTrack.GetPrimaryTrackLocalPosition();
xyz = fCrystalData->CoordinatesFromBoxToLattice(xyz0);
x=xyz.x();
y=xyz.y();
z=xyz.z();
momentumDirection=fastTrack.GetPrimaryTrackLocalDirection();
//angle in the co-rotating reference system within a channel
//(!!! ONLY FORWARD DIRECTION, momentumDirection.getZ()>0,
//valid for high energies defined by the standard energy cuts)
tx0 = std::atan(momentumDirection.x()/momentumDirection.z());
ty0 = std::atan(momentumDirection.y()/momentumDirection.z());
//angles in the co-rotating reference system within a channel
tx = fCrystalData->AngleXFromBoxToLattice(tx0,z);
ty = ty0;
etotalToSetParticleProperties = etotal*0.999;
G4bool inCrystal=true;//flag necessary to escape the cycle (at inCrystal=0;)
//do calculations until the particle is inside the volume
do
{
//remember the global time before the next step dz
tGlobalPreStep=tGlobal;
//remember the coordinates before the next step dz
xyz0PreStep = xyz0;
//remember the angles and the total energy before the step dz
txPreStep = tx;
tyPreStep = ty;
etotalPreStep = etotal;
dz = fCrystalData->GetSimulationStep(tx,ty);
dzd3=dz/3;
dzd8=dz/8;
//trajectory calculation:
//Runge-Cutt "3/8"
//fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ() is due to dependence of
//the radius on x; GetCurv gets 1/R for the central ("central plane/axis")
//first step
kvx1=fCrystalData->Ex(x,y);
x1=x+tx*dzd3;
tx1=tx+(kvx1-fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ())*dzd3;
if (fCrystalData->GetModel()==2)
{
kvy1=fCrystalData->Ey(x,y);
y1=y+ty*dzd3;
ty1=ty+kvy1*dzd3;
}
//second step
kvx2=fCrystalData->Ex(x1,y1);
x2=x-tx*dzd3+tx1*dz;
tx2=tx-(kvx1-fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ())*dzd3+
(kvx2-fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ())*dz;
if (fCrystalData->GetModel()==2)
{
kvy2=fCrystalData->Ey(x1,y1);
y2=y-ty*dzd3+ty1*dz;
ty2=ty-kvy1*dzd3+kvy2*dz;
}
//third step
kvx3=fCrystalData->Ex(x2,y2);
x3=x+(tx-tx1+tx2)*dz;
tx3=tx+(kvx1-kvx2+kvx3-fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ())*dz;
if (fCrystalData->GetModel()==2)
{
kvy3=fCrystalData->Ey(x2,y2);
y3=y+(ty-ty1+ty2)*dz;
ty3=ty+(kvy1-kvy2+kvy3)*dz;
}
//fourth step
kvx4=fCrystalData->Ex(x3,y3);
x4=x+(tx+3.*tx1+3.*tx2+tx3)*dzd8;
tx4=tx+(kvx1+3.*kvx2+3.*kvx3+kvx4)*dzd8-
fCrystalData->GetCurv()*fCrystalData->GetCorrectionZ()*dz;
if (fCrystalData->GetModel()==2)
{
kvy4=fCrystalData->Ey(x3,y3);
y4=y+(ty+3.*ty1+3.*ty2+ty3)*dzd8;
ty4=ty+(kvy1+3.*kvy2+3.*kvy3+kvy4)*dzd8;
}
else
{
y4 =y+ty*dz;
ty4=ty;
}
x=x4;
tx=tx4;
y=y4;
ty=ty4;
z+=dz*fCrystalData->GetCorrectionZ();//motion along the z coordinate
//("central plane/axis", no current plane/axis)
xyz = fCrystalData->ChannelChange(x,y,z);
x=xyz.x();
y=xyz.y();
z=xyz.z();
//the coordinates in the local reference system of the volume
//this vector will be used in the cycle escape condition and
//in the radiation model (if activated)
xyz0=fCrystalData->CoordinatesFromLatticeToBox(xyz);
momentumDirectionStep=
dz*std::sqrt(1+std::pow(std::tan(tx),2)+std::pow(std::tan(ty),2));
tGlobal+=momentumDirectionStep/(fCrystalData->GetBeta())/CLHEP::c_light;
//default scattering and energy loss 0
scatteringAnglesAndEnergyLoss = G4ThreeVector(0.,0.,0.);
//calculate separately for each element of the crystal
for (G4int i = 0; i < fCrystalData->GetNelements(); i++)
{
//effective step taking into account nuclear density along the trajectory
effectiveStep = momentumDirectionStep*fCrystalData->NuclearDensity(x,y,i);
//Coulomb scattering on screened atomic potential (both multiple and single)
scatteringAnglesAndEnergyLoss += fCrystalData->
CoulombAtomicScattering(effectiveStep,momentumDirectionStep,i);
//Amorphous part of ionization energy losses
etotal-=fCrystalData->IonizationLosses(momentumDirectionStep, i);
}
//electron scattering and coherent part of ionization energy losses
scatteringAnglesAndEnergyLoss += fCrystalData->CoulombElectronScattering(
fCrystalData->MinIonizationEnergy(x,y),
fCrystalData->ElectronDensity(x,y),
momentumDirectionStep);
tx += scatteringAnglesAndEnergyLoss.x();
ty += scatteringAnglesAndEnergyLoss.y();
etotal -= scatteringAnglesAndEnergyLoss.z();
// recalculate the energy depended parameters
//(only if the energy decreased enough, not at each step)
if (etotalToSetParticleProperties>etotal)
{
fCrystalData->SetParticleProperties(etotal, mass, charge, hadron);
etotalToSetParticleProperties = etotal*0.999;
}
//chain of conditions to escape the cycle
// if Inside(xyz0)==kInside has been already true
//(a particle has been inside the crystal)
if (inside)
{
// if low energy
if (etotal-mass<=GetLowKineticEnergyLimit(fastTrack.GetPrimaryTrack()->
GetParticleDefinition()->
GetParticleDefinitionID()))
{inCrystal = false;}//escape the cycle
//check if the angle w.r.t. the axes or planes is too high =>
//return to standard Geant4:
else if (fCrystalData->GetModel()==1) //1D model, field of planes
{
//if the angle w.r.t. the planes is too high
if (std::abs(tx) >=
lindhardAngleNumberHighLimit0*fCrystalData->GetLindhardAngle())
{inCrystal = false;}//escape the cycle
}
else if (fCrystalData->GetModel()==2) //2D model, field of axes
{
//if the angle w.r.t. the axes is too high
if (std::sqrt(tx*tx+ty*ty) >= lindhardAngleNumberHighLimit0*
fCrystalData->GetLindhardAngle())
{inCrystal = false;}//escape the cycle
}
//radiation production & radiation energy losses
//works only if the radiation model is activated
if (fRad)
{
//back to the local reference system of the volume
tx0 = fCrystalData->AngleXFromLatticeToBox(tx,z);
ty0 = ty;
//xyz0 was calculated above
//running the radiation model and checking if a photon has been emitted
if(fBaierKatkov->DoRadiation(etotal,mass,
tx0,ty0,
scatteringAnglesAndEnergyLoss.x(),
scatteringAnglesAndEnergyLoss.y(),
momentumDirectionStep,tGlobal,xyz0,
crystallogic->
GetSolid()->
Inside(xyz0)!=kInside&&inCrystal))
// also it was checked if the particle is escaping the volume
// calculate the radiation integral immidiately in this case
{
//a photon has been emitted!
//shift the particle back into the radiation point
etotal = fBaierKatkov->GetParticleNewTotalEnergy();
tx0 = fBaierKatkov->GetParticleNewAngleX();
ty0 = fBaierKatkov->GetParticleNewAngleY();
tGlobal = fBaierKatkov->GetNewGlobalTime();
xyz0 = fBaierKatkov->GetParticleNewCoordinateXYZ();
//add secondary photon
fBaierKatkov->GeneratePhoton(fastStep);
//particle energy was changed
fCrystalData->SetParticleProperties(etotal, mass, charge, hadron);
//coordinates in the co-rotating reference system within a channel
xyz = fCrystalData->CoordinatesFromBoxToLattice(xyz0);
x=xyz.x();
y=xyz.y();
z=xyz.z();
//angles in the co-rotating reference system within a channel
tx = fCrystalData->AngleXFromBoxToLattice(tx0,z);
ty = ty0;
}
}
//precise check if the particle is escaping the volume
if (crystallogic->GetSolid()->
Inside(xyz0)!=kInside)
{
//one step back to remain inside the volume
//after the escape of the volume
tGlobal = tGlobalPreStep;
xyz0 = xyz0PreStep;
tx = txPreStep;
ty = tyPreStep;
etotal = etotalPreStep;
z-=dz*fCrystalData->GetCorrectionZ();
// change the flag => this particle will not enter
// the model before escape this volume
inCrystal = false; //escape the cycle
}
}
else
{
// if Inside(xyz0)==kInside we can enable checking of particle escape
if (crystallogic->GetSolid()->
Inside(xyz0)==kInside)
{inside = true;}
// a very rare case, if a particle remains
// on the boundary and escapes the crystal
else if (crystallogic->GetSolid()->
Inside(xyz0)==kOutside)
{inCrystal = false;}//escape the cycle
}
}
while (inCrystal);
//the angles in the local reference system of the volume
tx0 = fCrystalData->AngleXFromLatticeToBox(tx,z);
ty0 = ty;
//set global time
fastStep.ProposePrimaryTrackFinalTime(tGlobal);
//set final position
fastStep.ProposePrimaryTrackFinalPosition(xyz0);
//set final kinetic energy
fastStep.ProposePrimaryTrackFinalKineticEnergy(etotal-
fastTrack.GetPrimaryTrack()->
GetParticleDefinition()->GetPDGMass());
//set final momentum direction
G4double momentumDirectionZ =
1./std::sqrt(1.+std::pow(std::tan(tx0),2)+std::pow(std::tan(ty0),2));
fastStep.ProposePrimaryTrackFinalMomentumDirection(
G4ThreeVector(momentumDirectionZ*std::tan(tx0),
momentumDirectionZ*std::tan(ty0),
momentumDirectionZ));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4ChannelingFastSimModel::Input(const G4Material *crystal, const G4String &lattice)
{
//initializing the class with containing all
//the crystal material and crystal lattice data and
//Channeling scattering and ionization processes
fCrystalData = new G4ChannelingFastSimCrystalData();
//setting all the crystal material and lattice data
fCrystalData->SetMaterialProperties(crystal,lattice);
//setting default low energy cuts for kinetic energy
SetLowKineticEnergyLimit(1*GeV,"proton");
SetLowKineticEnergyLimit(1*GeV,"anti_proton");
SetLowKineticEnergyLimit(200*MeV,"e-");
SetLowKineticEnergyLimit(200*MeV,"e+");
//set the model high limit of the angle expressed in [Lindhard angle] units
SetLindhardAngleNumberHighLimit(100.,"proton");
SetLindhardAngleNumberHighLimit(100.,"anti_proton");
SetLindhardAngleNumberHighLimit(100.,"e-");
SetLindhardAngleNumberHighLimit(100.,"e+");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4ChannelingFastSimModel::RadiationModelActivate()
{
fRad = true;
//activate the Baier-Katkov radiation model
fBaierKatkov = new G4BaierKatkov();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,485 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4VChannelingFastSimCrystalData.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
G4VChannelingFastSimCrystalData::G4VChannelingFastSimCrystalData()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VChannelingFastSimCrystalData::~G4VChannelingFastSimCrystalData(){;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VChannelingFastSimCrystalData::SetGeometryParameters
(const G4LogicalVolume *crystallogic)
{
G4int crystalID = crystallogic->GetInstanceID();
//set bending angle if the volume exists in the list, otherwise default = 0
(fMapBendingAngle.count(crystalID) > 0)
? SetBendingAngle(fMapBendingAngle[crystalID],crystallogic)
: SetBendingAngle(0.,crystallogic);
//set miscut angle if the volume exists in the list, otherwise default = 0
(fMapMiscutAngle.count(crystalID) > 0)
? SetMiscutAngle(fMapMiscutAngle[crystalID],crystallogic)
: SetMiscutAngle(0.,crystallogic);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VChannelingFastSimCrystalData::SetBendingAngle(G4double tetab,
const G4LogicalVolume* crystallogic)
{
G4int crystalID = crystallogic->GetInstanceID();
//set the bending angle for this logical volume
fMapBendingAngle[crystalID]=tetab;
G4ThreeVector limboxmin;//minimal limits of the box bounding the logical volume
G4ThreeVector limboxmax;//maximal limits of the box bounding the logical volume
//save the limits of the box bounding the logical volume
crystallogic->GetSolid()->BoundingLimits(limboxmin,limboxmax);
//bounding box half dimensions
fHalfDimBoundingBox = (limboxmax-limboxmin)/2.;
G4double lcr = limboxmax.getZ()-limboxmin.getZ();//crystal thickness
fBendingAngle=std::abs(tetab);
if (fBendingAngle<0.000001)//no bending less then 1 urad
{
fBent=0;
fBendingAngle=0.;
fBendingR=0.;//just for convenience (infinity in reality)
fBending2R=0.;
fBendingRsquare=0.;
fCurv=0.;
G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
G4cout << "Warning: bending angle is lower than 1 urad => set to 0" << G4endl;
}
else
{
fBent=1;
fBendingR=lcr/fBendingAngle;
fBending2R=2.*fBendingR;
fBendingRsquare=fBendingR*fBendingR;
fCurv=1./fBendingR;
if (tetab<0.)
{
G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
G4cout << "Warning: bending angle is negative => set to be positive" << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VChannelingFastSimCrystalData::SetMiscutAngle(G4double tetam,
const G4LogicalVolume *crystallogic)
{
G4int crystalID = crystallogic->GetInstanceID();
//set the bending angle for this logical volume
fMapMiscutAngle[crystalID]=tetam;
// fMiscutAngle>0: rotation of xz coordinate planes clockwise in the xz plane
fMiscutAngle=tetam;
if (std::abs(tetam)>1.*mrad)
{
G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
G4cout << "Warning: miscut angle is higher than 1 mrad => " << G4endl;
G4cout << "coordinate transformation routines may be unstable" << G4endl;
}
fCosMiscutAngle=std::cos(fMiscutAngle);
fSinMiscutAngle=std::sin(fMiscutAngle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VChannelingFastSimCrystalData::SetParticleProperties(G4double etotal,
G4double mass,
G4double charge,
G4bool ifhadron)
{
G4double teta1;
fZ2=charge;
G4double zz22=fZ2*fZ2;
fHadron=ifhadron;
// particle momentum and energy
G4double t=etotal*etotal-mass*mass; // economy of operations
fPz=std::sqrt(t); // momentum of particle
fPV=t/etotal; // pv
fBeta=fPz/etotal; // velocity/c
fTetaL = std::sqrt(fVmax2/fPV); //Lindhard angle
fChannelingStep = fChangeStep/fTetaL; //standard simulation step
// Energy losses
fV2 = fBeta*fBeta; // particle (velocity/c)^2
fGamma = etotal/mass; // Lorentz factor
fMe2Gamma = 2*CLHEP::electron_mass_c2*fGamma;
// max ionization losses
fTmax = fMe2Gamma*fGamma*fV2/
(CLHEP::electron_mass_c2/mass*CLHEP::electron_mass_c2/mass +
1. + fMe2Gamma/mass);
for(G4int i=0; i<fNelements; i++)
{
// minimal scattering angle by coulomb scattering on nuclei
// defining by shielding by electrons
// teta1=hdc/(fPz*fRF)*DSQRT(1.13D0+3.76D0*(alpha*fZ1*fZ2/fBeta)**2){ev*cm/(eV*cm)}
teta1=fTeta10[i]*std::sqrt(1.13+fK40[i]*zz22/fV2); // /fPz later to speed up
// the calculations
// the coefficient for multiple scattering
fBB[i]=teta1*teta1*fPu11[i];
fE1XBbb[i]=expint(fBB[i]);
fBBDEXP[i]=(1.+fBB[i])*std::exp(fBB[i]);
// necessary for suppression of incoherent scattering
// by the atomic correlations in crystals for single scattering on nucleus
// (screened atomic potential): EXP(-(fPz*teta*fU1)**2)=EXP(-fPzu11*teta**2).GE.ksi
// =>no scattering
fPzu11[i]=fPu11[i]*fPz*fPz;
teta1=teta1/fPz; //
fTeta12[i]=teta1*teta1;
// maximal scattering angle by coulomb scattering on nuclei
// defining by nucleus radius
// tetamax=hc/(fPz*1.D-6*fR0*fAN**(1.D0/3.D0))// {Mev*fermi/(MeV*fermi)}
G4double tetamax=fTetamax0[i]/fPz;
fTetamax2[i]=tetamax*tetamax;
fTetamax12[i]=fTeta12[i]+fTetamax2[i];
// a cofficient in a formula for scattering (for high speed of simulation)
// fK2=(fZ2*alpha*hdc)**2*4.*pi*fN0*(fZ1/fPV)**2
// fK3=(fZ2*alpha*hdc)**2*4.*pi*fN0/(fPV)**2
fK2[i]=fK20[i]*zz22/fPV/fPV;
}
// nuclear diffractive scattering angle
//tetaQEL=1./sqrt(2.*(9.26-4.94/sqrt(fPz/GeV)+0.28*log(fPz/GeV)));
fK3=fK30/fV2;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::GetLindhardAngle(G4double etotal, G4double mass)
{
G4double pv0 = etotal-mass*mass/etotal;
return std::sqrt(2*fVmax/pv0); //Calculate the value of the Lindhard angle
//(!!! the value for a straight crystal)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::GetLindhardAngle()
{
return fTetaL; //return the Lindhard angle value calculated in SetParticleProperties
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::GetSimulationStep(G4double tx,G4double ty)
{
G4double simulationstep;
//find angle of particle w.r.t. the plane or axis
G4double angle=0.;
if (iModel==1)//1D model
{
angle = std::abs(tx);
}
else if (iModel==2)//2D model
{
angle = std::sqrt(tx*tx+ty*ty);
}
//compare this angle with the Lindhard angle
if (angle<fTetaL)
{
simulationstep = fChannelingStep;
}
else
{
simulationstep = fChangeStep/angle;
}
return simulationstep;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::GetMaxSimulationStep(G4double etotal,
G4double mass)
{
//standard value of step for channeling particles which is the maximal possible step
return fChangeStep/GetLindhardAngle(etotal, mass);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4VChannelingFastSimCrystalData::CoulombAtomicScattering(
G4double effectiveStep,
G4double step,
G4int ielement)
{
G4double tx = 0.;//horizontal scattering angle
G4double ty = 0.;//vertical scattering angle
G4double ksi=0.1;
// calculation of the teta2-minimal possible angle of a single scattering
G4double e1=fK2[ielement]*effectiveStep; //for high speed of a program
// (real formula is (4*pi*fN0*wpl(x)*dz*fZ1*zz2*alpha*hdc/fPV)**2)
G4double teta122=fTetamax12[ielement]/(ksi*fTetamax12[ielement]/e1+1.);
// teta122=fTeta12+teta22=teta1^2+teta2^2
G4double teta22;
G4double t;
// if the angle of a single scattering is less teta1 - minimal possible
// angle of coulomb scattering defining by the electron shielding than
// multiple scattering by both nuclei and electrons and electrons will not
// occur => minimal possible angle of a single scattering is equal to teta1
if (teta122<=fTeta12[ielement]*1.000125)
{
teta22=0.;
teta122=fTeta12[ielement];
}
else
{
teta22=teta122-fTeta12[ielement];
G4double aa=teta22/fTeta12[ielement];
G4double aa1=1.+aa;
// crystal, with scattering suppression
G4double tetamsi=e1*(std::log(aa1)+
(1.-std::exp(-aa*fBB[ielement]))/aa1+
fBBDEXP[ielement]*
(expint(fBB[ielement]*aa1)-fE1XBbb[ielement]));
// sumilation of multiple coulomb scattering by nuclei and electrons
// for high speed of a program, real formula is
// 4*pi*fN0*wpl(x)*dz*(fZ1*zz2*alpha*hdc/fPV)**2*
// *(ln(1+a)+(1-exp(-a*b))/(1+a)+(1+b)*exp(b)*(E1XB(b*(1+a))-E1XB(b)))
ksi=G4UniformRand();
t=std::sqrt(-tetamsi*std::log(ksi));
ksi=G4UniformRand();
tx+=t*std::cos(CLHEP::twopi*ksi);
ty+=t*std::sin(CLHEP::twopi*ksi);
}
// simulation of single coulomb scattering by nuclei (with screened potential)
G4double zss=0.;
G4double dzss=step;
// (calculation of a distance, at which another single scattering can happen)
ksi=G4UniformRand();
zss=-std::log(ksi)*step/(e1*(1./teta122-1./fTetamax12[ielement]));
G4double tt;
// At some step several single scattering can occur.
// So,if the distance of the next scattering is less than the step,
// another scattering can occur. If the distance of the next scattering
// is less than the difference between the step and the distance of
// the previous scattering, another scattering can occur. And so on, and so on.
// In the cycle we simulate each of them. The cycle is finished, when
// the remaining part of step is less than a distance of the next single scattering.
//********************************************
// if at a step a single scattering occurs
while (zss<dzss)
{
// simulation by Monte-Carlo of angles of single scattering
ksi=G4UniformRand();
tt=fTetamax12[ielement]/(1.+ksi*(fTetamax2[ielement]-teta22)/teta122)-
fTeta12[ielement];
ksi=G4UniformRand();
// suppression of incoherent scattering by the atomic correlations in crystals
t=fPzu11[ielement]*tt;
t=std::exp(-t);
if (t<ksi) //if scattering takes place
{
//scattering angle
t=std::sqrt(tt);
ksi=G4UniformRand();
tx+=t*std::cos(CLHEP::twopi*ksi);
ty+=t*std::sin(CLHEP::twopi*ksi);
}
dzss-=zss;
// (calculation of a distance, at which another single scattering can happen)
ksi=G4UniformRand();
zss=-std::log(ksi)*step/(e1*(1./teta122-1./fTetamax12[ielement]));
}
//********************************************
return G4ThreeVector(tx,ty,0.);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ThreeVector G4VChannelingFastSimCrystalData::CoulombElectronScattering(
G4double eMinIonization,
G4double electronDensity,
G4double step)
{
G4double zss=0.;
G4double dzss=step;
G4double ksi = 0.;
G4double tx = 0.;//horizontal scattering angle
G4double ty = 0.;//vertical scattering angle
G4double eloss = 0.;//energy loss
// eMinIonization - minimal energy transfered to electron
// a cut to reduce the number of calls of electron scattering
// is needed only at low density regions, in many cases does not do anything at all
if (eMinIonization<0.5*eV){eMinIonization=0.5*eV;}
// single scattering on electrons routine
if ((eMinIonization<fTmax)&&(electronDensity>DBL_EPSILON))
{
// (calculation of a distance, at which another single scattering can happen)
// simulation of scattering length (by the same way single scattering by nucleus
ksi=G4UniformRand();
zss=-1.0*std::log(ksi)/(fK3*electronDensity)/(1./eMinIonization-1./fTmax);
//********************************************
// if at a step a single scattering occur
while (zss<dzss)
{
// simulation by Monte-Carlo of angles of single scattering
ksi=G4UniformRand();
// energy transfered to electron
G4double e1=eMinIonization/(1.-ksi*(1.-eMinIonization/fTmax));
// scattering angle
G4double t=std::sqrt(e1*(e1+2.*CLHEP::electron_mass_c2))/fPz;
// energy losses
if (fHadron) {eloss=e1;} // we don't calculate ionization losses for e+-
ksi=G4UniformRand();
tx+=t*std::cos(CLHEP::twopi*ksi);
ty+=t*std::sin(CLHEP::twopi*ksi);
dzss-=zss;
// (calculation of a distance, at which another single scattering can happen)
// simulation of scattering length
// (by the same way single scattering by nucleus
ksi=G4UniformRand();
zss=-1.0*std::log(ksi)/(fK3*electronDensity)/(1./eMinIonization-1./fTmax);
}
//********************************************
}
return G4ThreeVector(tx,ty,eloss);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::IonizationLosses(G4double dz,
G4int ielement)
{
G4double elosses = 0.;
if (fHadron) {elosses=fKD[ielement]/fV2*
(std::log(fMe2Gamma*fV2/fI0[ielement]/fGamma) - fV2)*dz;}
return elosses;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VChannelingFastSimCrystalData::expint(G4double X)
{
// ============================================
// Purpose: Compute exponential integral E1(x)
// Input : x --- Argument of E1(x)
// Output: E1 --- E1(x)
// ============================================
G4double E1, R, T, T0;
G4int M;
if (X==0)
{
E1=1.e300;
}
else if (X<=1.)
{
E1=1.;
R=1.;
for(int K=1; K<=25; K++)
{
R=-R*K*X/std::pow(K+1.,2.);
E1=E1+R;
if (std::abs(R)<=std::abs(E1)*1.0e-15) {break;}
}
E1=-0.5772156649015328-std::log(X)+X*E1;
}
else
{
M=20+std::trunc(80.0/X);
T0=0.;
for(int K=M; K>=1; K--)
{
T0=K/(1.0+K/(X+T0));
}
T=1.0/(X+T0);
E1=std::exp(-X)*T;
}
return E1;
}