Import Geant4 11.2.0.beta source tree
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user