Garfield++ v1r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Garfield::MediumMagboltz Class Reference

#include <MediumMagboltz.hh>

+ Inheritance diagram for Garfield::MediumMagboltz:

Public Member Functions

 MediumMagboltz ()
 
 ~MediumMagboltz ()
 
bool SetMaxElectronEnergy (const double e)
 
double GetMaxElectronEnergy () const
 
bool SetMaxPhotonEnergy (const double e)
 
double GetMaxPhotonEnergy () const
 
void EnableEnergyRangeAdjustment ()
 
void DisableEnergyRangeAdjustment ()
 
void EnableAnisotropicScattering ()
 
void DisableAnisotropicScattering ()
 
void SetSplittingFunctionOpalBeaty ()
 
void SetSplittingFunctionGreenSawada ()
 
void SetSplittingFunctionFlat ()
 
void EnableDeexcitation ()
 
void DisableDeexcitation ()
 
void EnableRadiationTrapping ()
 
void DisableRadiationTrapping ()
 
void EnablePenningTransfer (const double r, const double lambda)
 
void EnablePenningTransfer (const double r, const double lambda, std::string gasname)
 
void DisablePenningTransfer ()
 
void DisablePenningTransfer (std::string gasname)
 
void EnableCrossSectionOutput ()
 
void DisableCrossSectionOutput ()
 
void SetExcitationScalingFactor (const double r, std::string gasname)
 
bool Initialise (const bool verbose=false)
 
void PrintGas ()
 
double GetElectronNullCollisionRate (const int band)
 
double GetElectronCollisionRate (const double e, const int band)
 
double GetElectronCollisionRate (const double e, const int level, const int band)
 
bool GetElectronCollision (const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, int &nion, int &ndxc, int &band)
 
int GetNumberOfIonisationProducts ()
 
bool GetIonisationProduct (const int i, int &type, double &energy)
 
void ComputeDeexcitation (int iLevel, int &fLevel)
 
int GetNumberOfDeexcitationProducts ()
 
bool GetDeexcitationProduct (const int i, double &t, double &s, int &type, double &energy)
 
double GetPhotonCollisionRate (const double &e)
 
bool GetPhotonCollision (const double e, int &type, int &level, double &e1, double &ctheta, int &nsec, double &esec)
 
void ResetCollisionCounters ()
 
int GetNumberOfElectronCollisions () const
 
int GetNumberOfElectronCollisions (int &nElastic, int &nIonising, int &nAttachment, int &nInelastic, int &nExcitation, int &nSuperelastic) const
 
int GetNumberOfLevels ()
 
bool GetLevel (const int i, int &ngas, int &type, std::string &descr, double &e)
 
int GetNumberOfElectronCollisions (const int level) const
 
int GetNumberOfPenningTransfers () const
 
int GetNumberOfPhotonCollisions () const
 
int GetNumberOfPhotonCollisions (int &nElastic, int &nIonising, int &nInelastic) const
 
void RunMagboltz (const double e, const double b, const double btheta, const int ncoll, bool verbose, double &vx, double &vy, double &vz, double &dl, double &dt, double &alpha, double &eta, double &vxerr, double &vyerr, double &vzerr, double &dlerr, double &dterr, double &alphaerr, double &etaerr, double &alphatof)
 
void GenerateGasTable (const int numCollisions=10, const bool verbose=true)
 
- Public Member Functions inherited from Garfield::MediumGas
 MediumGas ()
 
 ~MediumGas ()
 
bool IsGas () const
 
bool SetComposition (const std::string gas1, const double f1=1., const std::string gas2="", const double f2=0., const std::string gas3="", const double f3=0., const std::string gas4="", const double f4=0., const std::string gas5="", const double f5=0., const std::string gas6="", const double f6=0.)
 
void GetComposition (std::string &gas1, double &f1, std::string &gas2, double &f2, std::string &gas3, double &f3, std::string &gas4, double &f4, std::string &gas5, double &f5, std::string &gas6, double &f6)
 
void GetComponent (const unsigned int &i, std::string &label, double &f)
 
void SetAtomicNumber (const double &z)
 
double GetAtomicNumber () const
 
void SetAtomicWeight (const double &a)
 
double GetAtomicWeight () const
 
void SetNumberDensity (const double &n)
 
double GetNumberDensity () const
 
void SetMassDensity (const double &rho)
 
double GetMassDensity () const
 
bool LoadGasFile (const std::string &filename)
 
bool WriteGasFile (const std::string &filename)
 
void PrintGas ()
 
bool LoadIonMobility (const std::string &filename)
 
void SetExtrapolationMethodExcitationRates (const std::string extrLow, const std::string extrHigh)
 
void SetExtrapolationMethodIonisationRates (const std::string extrLow, const std::string extrHigh)
 
void SetInterpolationMethodExcitationRates (const int intrp)
 
void SetInterpolationMethodIonisationRates (const int intrp)
 
double ScaleElectricField (const double &e) const
 
double UnScaleElectricField (const double &e) const
 
double ScaleDiffusion (const double &d) const
 
double ScaleDiffusionTensor (const double &d) const
 
double ScaleTownsend (const double &alpha) const
 
double ScaleAttachment (const double &eta) const
 
bool GetPhotoabsorptionCrossSection (const double &e, double &sigma, const unsigned int &i)
 
- Public Member Functions inherited from Garfield::Medium
 Medium ()
 
virtual ~Medium ()
 
int GetId () const
 
std::string GetName () const
 
virtual bool IsGas () const
 
virtual bool IsSemiconductor () const
 
void SetTemperature (const double &t)
 
double GetTemperature () const
 
void SetPressure (const double &p)
 
double GetPressure () const
 
void SetDielectricConstant (const double &eps)
 
double GetDielectricConstant () const
 
unsigned int GetNumberOfComponents () const
 
virtual void GetComponent (const unsigned int &i, std::string &label, double &f)
 
virtual void SetAtomicNumber (const double &z)
 
virtual double GetAtomicNumber () const
 
virtual void SetAtomicWeight (const double &a)
 
virtual double GetAtomicWeight () const
 
virtual void SetNumberDensity (const double &n)
 
virtual double GetNumberDensity () const
 
virtual void SetMassDensity (const double &rho)
 
virtual double GetMassDensity () const
 
virtual void EnableDrift ()
 
void DisableDrift ()
 
virtual void EnablePrimaryIonisation ()
 
void DisablePrimaryIonisation ()
 
bool IsDriftable () const
 
bool IsMicroscopic () const
 
bool IsIonisable () const
 
void SetW (const double &w)
 
double GetW ()
 
void SetFanoFactor (const double &f)
 
double GetFanoFactor ()
 
virtual bool ElectronVelocity (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
 
virtual bool ElectronDiffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
 
virtual bool ElectronDiffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double cov[3][3])
 
virtual bool ElectronTownsend (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
 
virtual bool ElectronAttachment (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
 
virtual double GetElectronEnergy (const double px, const double py, const double pz, double &vx, double &vy, double &vz, const int band=0)
 
virtual void GetElectronMomentum (const double e, double &px, double &py, double &pz, int &band)
 
virtual double GetElectronNullCollisionRate (const int band=0)
 
virtual double GetElectronCollisionRate (const double e, const int band=0)
 
virtual bool GetElectronCollision (const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, int &nion, int &ndxc, int &band)
 
virtual int GetNumberOfIonisationProducts ()
 
virtual bool GetIonisationProduct (const int i, int &type, double &energy)
 
virtual int GetNumberOfDeexcitationProducts ()
 
virtual bool GetDeexcitationProduct (const int i, double &t, double &s, int &type, double &energy)
 
virtual bool HoleVelocity (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
 
virtual bool HoleDiffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
 
virtual bool HoleDiffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double cov[3][3])
 
virtual bool HoleTownsend (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
 
virtual bool HoleAttachment (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
 
virtual bool IonVelocity (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
 
virtual bool IonDiffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
 
virtual bool IonDissociation (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &diss)
 
void SetFieldGrid (double emin, double emax, int ne, bool logE, double bmin=0., double bmax=0., int nb=1, double amin=0., double amax=0., int na=1)
 
void SetFieldGrid (const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles)
 
void GetFieldGrid (std::vector< double > &efields, std::vector< double > &bfields, std::vector< double > &angles)
 
bool GetElectronVelocityE (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetElectronVelocityExB (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetElectronVelocityB (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetElectronLongitudinalDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
 
bool GetElectronTransverseDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
 
bool GetElectronTownsend (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &alpha)
 
bool GetElectronAttachment (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &eta)
 
bool GetHoleVelocityE (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetHoleVelocityExB (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetHoleVelocityB (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
 
bool GetHoleLongitudinalDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
 
bool GetHoleTransverseDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
 
bool GetHoleTownsend (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &alpha)
 
bool GetHoleAttachment (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &eta)
 
bool GetIonMobility (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &mu)
 
bool GetIonLongitudinalDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
 
bool GetIonTransverseDiffusion (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
 
bool GetIonDissociation (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &diss)
 
void ResetElectronVelocity ()
 
void ResetElectronDiffusion ()
 
void ResetElectronTownsend ()
 
void ResetElectronAttachment ()
 
void ResetHoleVelocity ()
 
void ResetHoleDiffusion ()
 
void ResetHoleTownsend ()
 
void ResetHoleAttachment ()
 
void ResetIonMobility ()
 
void ResetIonDiffusion ()
 
void ResetIonDissociation ()
 
bool SetIonMobility (const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, const double &mu)
 
bool SetIonMobility (const std::vector< double > &fields, const std::vector< double > &mobilities)
 
void SetExtrapolationMethodVelocity (const std::string &extrLow, const std::string &extrHigh)
 
void SetExtrapolationMethodDiffusion (const std::string &extrLow, const std::string &extrHigh)
 
void SetExtrapolationMethodTownsend (const std::string &extrLow, const std::string &extrHigh)
 
void SetExtrapolationMethodAttachment (const std::string &extrLow, const std::string &extrHigh)
 
void SetExtrapolationMethodIonMobility (const std::string &extrLow, const std::string &extrHigh)
 
void SetExtrapolationMethodIonDissociation (const std::string &extrLow, const std::string &extrHigh)
 
void SetInterpolationMethodVelocity (const unsigned int &intrp)
 
void SetInterpolationMethodDiffusion (const unsigned int &intrp)
 
void SetInterpolationMethodTownsend (const unsigned int &intrp)
 
void SetInterpolationMethodAttachment (const unsigned int &intrp)
 
void SetInterpolationMethodIonMobility (const unsigned int &intrp)
 
void SetInterpolationMethodIonDissociation (const unsigned int &intrp)
 
virtual double ScaleElectricField (const double &e) const
 
virtual double UnScaleElectricField (const double &e) const
 
virtual double ScaleVelocity (const double &v) const
 
virtual double ScaleDiffusion (const double &d) const
 
virtual double ScaleDiffusionTensor (const double &d) const
 
virtual double ScaleTownsend (const double &alpha) const
 
virtual double ScaleAttachment (const double &eta) const
 
virtual double ScaleDissociation (const double &diss) const
 
virtual bool GetOpticalDataRange (double &emin, double &emax, const unsigned int &i=0)
 
virtual bool GetDielectricFunction (const double &e, double &eps1, double &eps2, const unsigned int &i=0)
 
virtual bool GetPhotoAbsorptionCrossSection (const double &e, double &sigma, const unsigned int &i=0)
 
virtual double GetPhotonCollisionRate (const double &e)
 
virtual bool GetPhotonCollision (const double e, int &type, int &level, double &e1, double &ctheta, int &nsec, double &esec)
 
void EnableDebugging ()
 
void DisableDebugging ()
 

Public Attributes

double fit3d4p
 
double fitHigh4p
 
double fit3dQCO2
 
double fit3dEtaCO2
 
double fit3dQCH4
 
double fit3dEtaCH4
 
double fit3dQC2H6
 
double fit3dEtaC2H6
 
double fit4pEtaCH4
 
double fit4pEtaC2H6
 
double fit4sEtaC2H6
 
double fitLineCut
 

Additional Inherited Members

- Protected Member Functions inherited from Garfield::MediumGas
bool GetGasInfo (const std::string gasname, double &a, double &z) const
 
bool GetGasName (const int gasnumber, const int version, std::string &gasname)
 
bool GetGasName (std::string input, std::string &gasname) const
 
bool GetGasNumberGasFile (const std::string input, int &number) const
 
- Protected Member Functions inherited from Garfield::Medium
double Interpolate1D (const double &e, const std::vector< double > &table, const std::vector< double > &fields, const unsigned int &intpMeth, const int &jExtr, const int &iExtr)
 
bool GetExtrapolationIndex (std::string extrStr, unsigned int &extrNb)
 
void CloneTable (std::vector< std::vector< std::vector< double > > > &tab, const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles, const unsigned int &intp, const unsigned int &extrLow, const unsigned int &extrHigh, const double init, const std::string label)
 
void CloneTensor (std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const unsigned int &n, const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles, const unsigned int &intp, const unsigned int &extrLow, const unsigned int &extrHigh, const double &init, const std::string &label)
 
void InitParamArrays (const unsigned int &eRes, const unsigned int &bRes, const unsigned int &aRes, std::vector< std::vector< std::vector< double > > > &tab, const double &val)
 
void InitParamTensor (const unsigned int &eRes, const unsigned int &bRes, const unsigned int &aRes, const unsigned int &tRes, std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const double &val)
 
- Protected Attributes inherited from Garfield::MediumGas
std::string gas [m_nMaxGases]
 
double fraction [m_nMaxGases]
 
double atWeight [m_nMaxGases]
 
double atNum [m_nMaxGases]
 
bool usePenning
 
double rPenningGlobal
 
double rPenningGas [m_nMaxGases]
 
double lambdaPenningGlobal
 
double lambdaPenningGas [m_nMaxGases]
 
double pressureTable
 
double temperatureTable
 
std::vector< std::vector< std::vector< double > > > tabTownsendNoPenning
 
bool m_hasExcRates
 
bool m_hasIonRates
 
std::vector< std::vector< std::vector< std::vector< double > > > > tabExcRates
 
std::vector< std::vector< std::vector< std::vector< double > > > > tabIonRates
 
int nExcListElements
 
std::vector< excListElementexcitationList
 
int nIonListElements
 
std::vector< ionListElementionisationList
 
unsigned int m_extrLowExcRates
 
unsigned int m_extrHighExcRates
 
unsigned int m_extrLowIonRates
 
unsigned int m_extrHighIonRates
 
unsigned int m_intpExcRates
 
unsigned int m_intpIonRates
 
- Protected Attributes inherited from Garfield::Medium
std::string m_className
 
int m_id
 
std::string m_name
 
double m_temperature
 
double m_pressure
 
double m_epsilon
 
unsigned int m_nComponents
 
double m_z
 
double m_a
 
double m_density
 
bool m_driftable
 
bool m_microscopic
 
bool m_ionisable
 
double m_w
 
double m_fano
 
bool m_isChanged
 
bool m_debug
 
unsigned int m_nEfields
 
unsigned int m_nBfields
 
unsigned int m_nAngles
 
std::vector< double > eFields
 
std::vector< double > bFields
 
std::vector< double > bAngles
 
bool m_map2d
 
bool m_hasElectronVelocityE
 
bool m_hasElectronVelocityB
 
bool m_hasElectronVelocityExB
 
bool m_hasElectronDiffLong
 
bool m_hasElectronDiffTrans
 
bool m_hasElectronDiffTens
 
bool m_hasElectronTownsend
 
bool m_hasElectronAttachment
 
std::vector< std::vector< std::vector< double > > > tabElectronVelocityE
 
std::vector< std::vector< std::vector< double > > > tabElectronVelocityExB
 
std::vector< std::vector< std::vector< double > > > tabElectronVelocityB
 
std::vector< std::vector< std::vector< double > > > tabElectronDiffLong
 
std::vector< std::vector< std::vector< double > > > tabElectronDiffTrans
 
std::vector< std::vector< std::vector< double > > > tabElectronTownsend
 
std::vector< std::vector< std::vector< double > > > tabElectronAttachment
 
std::vector< std::vector< std::vector< std::vector< double > > > > tabElectronDiffTens
 
bool m_hasHoleVelocityE
 
bool m_hasHoleVelocityB
 
bool m_hasHoleVelocityExB
 
bool m_hasHoleDiffLong
 
bool m_hasHoleDiffTrans
 
bool m_hasHoleDiffTens
 
bool m_hasHoleTownsend
 
bool m_hasHoleAttachment
 
std::vector< std::vector< std::vector< double > > > tabHoleVelocityE
 
std::vector< std::vector< std::vector< double > > > tabHoleVelocityExB
 
std::vector< std::vector< std::vector< double > > > tabHoleVelocityB
 
std::vector< std::vector< std::vector< double > > > tabHoleDiffLong
 
std::vector< std::vector< std::vector< double > > > tabHoleDiffTrans
 
std::vector< std::vector< std::vector< double > > > tabHoleTownsend
 
std::vector< std::vector< std::vector< double > > > tabHoleAttachment
 
std::vector< std::vector< std::vector< std::vector< double > > > > tabHoleDiffTens
 
bool m_hasIonMobility
 
bool m_hasIonDiffLong
 
bool m_hasIonDiffTrans
 
bool m_hasIonDissociation
 
std::vector< std::vector< std::vector< double > > > tabIonMobility
 
std::vector< std::vector< std::vector< double > > > tabIonDiffLong
 
std::vector< std::vector< std::vector< double > > > tabIonDiffTrans
 
std::vector< std::vector< std::vector< double > > > tabIonDissociation
 
int thrElectronTownsend
 
int thrElectronAttachment
 
int thrHoleTownsend
 
int thrHoleAttachment
 
int thrIonDissociation
 
unsigned int m_extrLowVelocity
 
unsigned int m_extrHighVelocity
 
unsigned int m_extrLowDiffusion
 
unsigned int m_extrHighDiffusion
 
unsigned int m_extrLowTownsend
 
unsigned int m_extrHighTownsend
 
unsigned int m_extrLowAttachment
 
unsigned int m_extrHighAttachment
 
unsigned int m_extrLowMobility
 
unsigned int m_extrHighMobility
 
unsigned int m_extrLowDissociation
 
unsigned int m_extrHighDissociation
 
unsigned int m_intpVelocity
 
unsigned int m_intpDiffusion
 
unsigned int m_intpTownsend
 
unsigned int m_intpAttachment
 
unsigned int m_intpMobility
 
unsigned int m_intpDissociation
 
- Static Protected Attributes inherited from Garfield::MediumGas
static const unsigned int m_nMaxGases = 6
 
- Static Protected Attributes inherited from Garfield::Medium
static int m_idCounter = -1
 

Detailed Description

Definition at line 10 of file MediumMagboltz.hh.

Constructor & Destructor Documentation

◆ MediumMagboltz()

Garfield::MediumMagboltz::MediumMagboltz ( )

Definition at line 23 of file MediumMagboltz.cc.

24 : MediumGas(),
25 eFinal(40.),
26 eStep(eFinal / nEnergySteps),
27 eHigh(1.e4),
28 eHighLog(log(eHigh)),
29 lnStep(1.),
30 useAutoAdjust(true),
31 useCsOutput(false),
32 nTerms(0),
33 useAnisotropic(true),
34 nPenning(0),
35 useDeexcitation(false),
36 useRadTrap(true),
37 nDeexcitations(0),
38 nIonisationProducts(0),
39 nDeexcitationProducts(0),
40 useOpalBeaty(true),
41 useGreenSawada(false),
42 eFinalGamma(20.),
43 eStepGamma(eFinalGamma / nEnergyStepsGamma) {
44
45 fit3d4p = fitHigh4p = 1.;
49 fit4sEtaC2H6 = 0.5;
50 fitLineCut = 1000;
51
52 m_className = "MediumMagboltz";
53
54 // Set physical constants in Magboltz common blocks.
55 Magboltz::cnsts_.echarg = ElementaryCharge * 1.e-15;
56 Magboltz::cnsts_.emass = ElectronMassGramme;
57 Magboltz::cnsts_.amu = AtomicMassUnit;
58 Magboltz::cnsts_.pir2 = BohrRadius * BohrRadius * Pi;
59 Magboltz::inpt_.ary = RydbergEnergy;
60
61 // Set parameters in Magboltz common blocks.
63 Magboltz::inpt_.nStep = nEnergySteps;
64 // Select the scattering model.
65 Magboltz::inpt_.nAniso = 2;
66 // Max. energy [eV]
67 Magboltz::inpt_.efinal = eFinal;
68 // Energy step size [eV]
69 Magboltz::inpt_.estep = eStep;
70 // Temperature and pressure
71 Magboltz::inpt_.akt = BoltzmannConstant * m_temperature;
72 Magboltz::inpt_.tempc = m_temperature - ZeroCelsius;
74 // Disable Penning transfer.
75 Magboltz::inpt_.ipen = 0;
76
77 // Initialise Penning parameters
78 for (int i = nMaxLevels; i--;) {
79 rPenning[i] = 0.;
80 lambdaPenning[i] = 0.;
81 }
82
83 m_isChanged = true;
84
87 m_microscopic = true;
88
89 // Initialize the collision counters.
90 nCollisionsDetailed.clear();
91 for (int i = nCsTypes; i--;) nCollisions[i] = 0;
92 for (int i = nCsTypesGamma; i--;) nPhotonCollisions[i] = 0;
93
94 ionProducts.clear();
95 dxcProducts.clear();
96
97 for (unsigned int i = 0; i < m_nMaxGases; ++i) scaleExc[i] = 1.;
98}
static const unsigned int m_nMaxGases
Definition: MediumGas.hh:82
bool m_microscopic
Definition: Medium.hh:309
double m_pressure
Definition: Medium.hh:295
virtual void EnableDrift()
Definition: Medium.hh:52
virtual void EnablePrimaryIonisation()
Definition: Medium.hh:54
unsigned int m_nComponents
Definition: Medium.hh:299
std::string m_className
Definition: Medium.hh:284
bool m_isChanged
Definition: Medium.hh:316
double m_temperature
Definition: Medium.hh:293
struct Garfield::Magboltz::@1 inpt_
struct Garfield::Magboltz::@3 cnsts_

◆ ~MediumMagboltz()

Garfield::MediumMagboltz::~MediumMagboltz ( )
inline

Definition at line 16 of file MediumMagboltz.hh.

16{}

Member Function Documentation

◆ ComputeDeexcitation()

void Garfield::MediumMagboltz::ComputeDeexcitation ( int  iLevel,
int &  fLevel 
)

Definition at line 5095 of file MediumMagboltz.cc.

5095 {
5096
5097 if (!useDeexcitation) {
5098 std::cerr << m_className << "::ComputeDeexcitation:\n";
5099 std::cerr << " Deexcitation is disabled.\n";
5100 return;
5101 }
5102
5103 // Make sure that the tables are updated.
5104 if (m_isChanged) {
5105 if (!Mixer()) {
5106 std::cerr << m_className << "::ComputeDeexcitation:\n";
5107 std::cerr << " Error calculating the collision rates table.\n";
5108 return;
5109 }
5110 m_isChanged = false;
5111 }
5112
5113 if (iLevel < 0 || iLevel >= nTerms) {
5114 std::cerr << m_className << "::ComputeDeexcitation:\n";
5115 std::cerr << " Level index is out of range.\n";
5116 return;
5117 }
5118
5119 iLevel = iDeexcitation[iLevel];
5120 if (iLevel < 0 || iLevel >= nDeexcitations) {
5121 std::cerr << m_className << "::ComputeDeexcitation:\n";
5122 std::cerr << " Level is not deexcitable.\n";
5123 return;
5124 }
5125
5126 ComputeDeexcitationInternal(iLevel, fLevel);
5127 if (fLevel >= 0 && fLevel < nDeexcitations) {
5128 fLevel = deexcitations[fLevel].level;
5129 }
5130}

◆ DisableAnisotropicScattering()

void Garfield::MediumMagboltz::DisableAnisotropicScattering ( )
inline

Definition at line 38 of file MediumMagboltz.hh.

38 {
39 useAnisotropic = false;
40 m_isChanged = true;
41 }

◆ DisableCrossSectionOutput()

void Garfield::MediumMagboltz::DisableCrossSectionOutput ( )
inline

Definition at line 66 of file MediumMagboltz.hh.

66{ useCsOutput = false; }

◆ DisableDeexcitation()

void Garfield::MediumMagboltz::DisableDeexcitation ( )
inline

Definition at line 50 of file MediumMagboltz.hh.

50{ useDeexcitation = false; }

◆ DisableEnergyRangeAdjustment()

void Garfield::MediumMagboltz::DisableEnergyRangeAdjustment ( )
inline

Definition at line 31 of file MediumMagboltz.hh.

31{ useAutoAdjust = false; }

◆ DisablePenningTransfer() [1/2]

void Garfield::MediumMagboltz::DisablePenningTransfer ( )

Definition at line 317 of file MediumMagboltz.cc.

317 {
318
319 for (int i = nTerms; i--;) {
320 rPenning[i] = 0.;
321 lambdaPenning[i] = 0.;
322 }
323 rPenningGlobal = 0.;
325
326 for (unsigned int i = 0; i < m_nMaxGases; ++i) {
327 rPenningGas[i] = 0.;
328 lambdaPenningGas[i] = 0.;
329 }
330
331 usePenning = false;
332}
double lambdaPenningGas[m_nMaxGases]
Definition: MediumGas.hh:98
double lambdaPenningGlobal
Definition: MediumGas.hh:97
double rPenningGas[m_nMaxGases]
Definition: MediumGas.hh:95

◆ DisablePenningTransfer() [2/2]

void Garfield::MediumMagboltz::DisablePenningTransfer ( std::string  gasname)

Definition at line 334 of file MediumMagboltz.cc.

334 {
335
336 // Get the "standard" name of this gas.
337 if (!GetGasName(gasname, gasname)) {
338 std::cerr << m_className << "::DisablePenningTransfer:\n";
339 std::cerr << " Gas " << gasname << " is not defined.\n";
340 return;
341 }
342
343 // Look for this gas in the present gas mixture.
344 bool found = false;
345 int iGas = -1;
346 for (unsigned int i = 0; i < m_nComponents; ++i) {
347 if (gas[i] == gasname) {
348 rPenningGas[i] = 0.;
349 lambdaPenningGas[i] = 0.;
350 found = true;
351 iGas = i;
352 break;
353 }
354 }
355
356 if (!found) {
357 std::cerr << m_className << "::DisablePenningTransfer:\n";
358 std::cerr << " Specified gas (" << gasname
359 << ") is not part of the present gas mixture.\n";
360 return;
361 }
362
363 int nLevelsFound = 0;
364 for (int i = nTerms; i--;) {
365 if (int(csType[i] / nCsTypes) == iGas) {
366 rPenning[i] = 0.;
367 lambdaPenning[i] = 0.;
368 } else {
369 if (csType[i] % nCsTypes == ElectronCollisionTypeExcitation &&
370 rPenning[i] > Small) {
371 ++nLevelsFound;
372 }
373 }
374 }
375
376 if (nLevelsFound <= 0) {
377 // There are no more excitation levels with r > 0.
378 std::cout << m_className << "::DisablePenningTransfer:\n";
379 std::cout << " Penning transfer globally switched off.\n";
380 usePenning = false;
381 }
382}
bool GetGasName(const int gasnumber, const int version, std::string &gasname)
Definition: MediumGas.cc:2045
std::string gas[m_nMaxGases]
Definition: MediumGas.hh:85

◆ DisableRadiationTrapping()

void Garfield::MediumMagboltz::DisableRadiationTrapping ( )
inline

Definition at line 53 of file MediumMagboltz.hh.

53{ useRadTrap = false; }

◆ EnableAnisotropicScattering()

void Garfield::MediumMagboltz::EnableAnisotropicScattering ( )
inline

Definition at line 34 of file MediumMagboltz.hh.

34 {
35 useAnisotropic = true;
36 m_isChanged = true;
37 }

◆ EnableCrossSectionOutput()

void Garfield::MediumMagboltz::EnableCrossSectionOutput ( )
inline

Definition at line 65 of file MediumMagboltz.hh.

65{ useCsOutput = true; }

◆ EnableDeexcitation()

void Garfield::MediumMagboltz::EnableDeexcitation ( )

Definition at line 177 of file MediumMagboltz.cc.

177 {
178
179 if (usePenning) {
180 std::cout << m_className << "::EnableDeexcitation:\n";
181 std::cout << " Penning transfer will be switched off.\n";
182 }
183 // if (useRadTrap) {
184 // std::cout << " Radiation trapping is switched on.\n";
185 // } else {
186 // std::cout << " Radiation trapping is switched off.\n";
187 // }
188 usePenning = false;
189 useDeexcitation = true;
190 m_isChanged = true;
191 nDeexcitationProducts = 0;
192}

◆ EnableEnergyRangeAdjustment()

void Garfield::MediumMagboltz::EnableEnergyRangeAdjustment ( )
inline

Definition at line 30 of file MediumMagboltz.hh.

30{ useAutoAdjust = true; }

◆ EnablePenningTransfer() [1/2]

void Garfield::MediumMagboltz::EnablePenningTransfer ( const double  r,
const double  lambda 
)

Definition at line 206 of file MediumMagboltz.cc.

207 {
208
209 if (r < 0. || r > 1.) {
210 std::cerr << m_className << "::EnablePenningTransfer:\n";
211 std::cerr << " Penning transfer probability must be "
212 << " in the range [0, 1].\n";
213 return;
214 }
215
216 rPenningGlobal = r;
217 if (lambda < Small) {
219 } else {
220 lambdaPenningGlobal = lambda;
221 }
222
223 std::cout << m_className << "::EnablePenningTransfer:\n";
224 std::cout << " Global Penning transfer parameters set to: \n";
225 std::cout << " r = " << rPenningGlobal << "\n";
226 std::cout << " lambda = " << lambdaPenningGlobal << " cm\n";
227
228 for (int i = nTerms; i--;) {
229 rPenning[i] = rPenningGlobal;
230 lambdaPenning[i] = lambdaPenningGlobal;
231 }
232
233 if (useDeexcitation) {
234 std::cout << m_className << "::EnablePenningTransfer:\n";
235 std::cout << " Deexcitation handling will be switched off.\n";
236 }
237 usePenning = true;
238}

Referenced by GarfieldPhysics::InitializePhysics().

◆ EnablePenningTransfer() [2/2]

void Garfield::MediumMagboltz::EnablePenningTransfer ( const double  r,
const double  lambda,
std::string  gasname 
)

Definition at line 240 of file MediumMagboltz.cc.

241 {
242
243 if (r < 0. || r > 1.) {
244 std::cerr << m_className << "::EnablePenningTransfer:\n";
245 std::cerr << " Penning transfer probability must be "
246 << " in the range [0, 1].\n";
247 return;
248 }
249
250 // Get the "standard" name of this gas.
251 if (!GetGasName(gasname, gasname)) {
252 std::cerr << m_className << "::EnablePenningTransfer:\n";
253 std::cerr << " Unknown gas name.\n";
254 return;
255 }
256
257 // Look for this gas in the present gas mixture.
258 bool found = false;
259 int iGas = -1;
260 for (unsigned int i = 0; i < m_nComponents; ++i) {
261 if (gas[i] == gasname) {
262 rPenningGas[i] = r;
263 if (lambda < Small) {
264 lambdaPenningGas[i] = 0.;
265 } else {
266 lambdaPenningGas[i] = lambda;
267 }
268 found = true;
269 iGas = i;
270 break;
271 }
272 }
273
274 if (!found) {
275 std::cerr << m_className << "::EnablePenningTransfer:\n";
276 std::cerr << " Specified gas (" << gasname
277 << ") is not part of the present gas mixture.\n";
278 return;
279 }
280
281 // Make sure that the collision rate table is updated.
282 if (m_isChanged) {
283 if (!Mixer()) {
284 std::cerr << m_className << "::EnablePenningTransfer:\n";
285 std::cerr << " Error calculating the collision rates table.\n";
286 return;
287 }
288 m_isChanged = false;
289 }
290
291 int nLevelsFound = 0;
292 for (int i = nTerms; i--;) {
293 if (int(csType[i] / nCsTypes) == iGas) {
294 if (csType[i] % nCsTypes == ElectronCollisionTypeExcitation) {
295 ++nLevelsFound;
296 }
297 rPenning[i] = rPenningGas[iGas];
298 lambdaPenning[i] = lambdaPenningGas[iGas];
299 }
300 }
301
302 if (nLevelsFound > 0) {
303 std::cout << m_className << "::EnablePenningTransfer:\n";
304 std::cout << " Penning transfer parameters for " << nLevelsFound
305 << " excitation levels set to:\n";
306 std::cout << " r = " << rPenningGas[iGas] << "\n";
307 std::cout << " lambda = " << lambdaPenningGas[iGas] << " cm\n";
308 } else {
309 std::cerr << m_className << "::EnablePenningTransfer:\n";
310 std::cerr << " Specified gas (" << gasname
311 << ") has no excitation levels in the present energy range.\n";
312 }
313
314 usePenning = true;
315}

◆ EnableRadiationTrapping()

void Garfield::MediumMagboltz::EnableRadiationTrapping ( )

Definition at line 194 of file MediumMagboltz.cc.

194 {
195
196 useRadTrap = true;
197 if (!useDeexcitation) {
198 std::cout << m_className << "::EnableRadiationTrapping:\n";
199 std::cout << " Radiation trapping is enabled"
200 << " but de-excitation is not.\n";
201 } else {
202 m_isChanged = true;
203 }
204}

◆ GenerateGasTable()

void Garfield::MediumMagboltz::GenerateGasTable ( const int  numCollisions = 10,
const bool  verbose = true 
)

Definition at line 5565 of file MediumMagboltz.cc.

5565 {
5566
5567 // Set the reference pressure and temperature.
5570
5571 // Initialize the parameter arrays.
5580
5584 m_hasElectronDiffLong = true;
5586 m_hasElectronTownsend = true;
5588
5589 m_hasExcRates = false;
5590 tabExcRates.clear();
5591 excitationList.clear();
5592 nExcListElements = 0;
5593 m_hasIonRates = false;
5594 tabIonRates.clear();
5595 ionisationList.clear();
5596 nIonListElements = 0;
5597
5598 m_hasIonMobility = false;
5599 m_hasIonDissociation = false;
5600 m_hasIonDiffLong = false;
5601 m_hasIonDiffTrans = false;
5602
5603 // gasBits = "TFTTFTFTTTFFFFFF";
5604 // The version number is 11 because there are slight
5605 // differences between the way these gas files are written
5606 // and the ones from Garfield. This is mainly in the way
5607 // the gas tables are stored.
5608 // versionNumber = 11;
5609
5610 double vx = 0., vy = 0., vz = 0.;
5611 double difl = 0., dift = 0.;
5612 double alpha = 0., eta = 0.;
5613 double vxerr = 0., vyerr = 0., vzerr = 0.;
5614 double diflerr = 0., difterr = 0.;
5615 double alphaerr = 0., etaerr = 0.;
5616 double alphatof = 0.;
5617
5618 // Run through the grid of E- and B-fields and angles.
5619 for (unsigned int i = 0; i < m_nEfields; ++i) {
5620 for (unsigned int j = 0; j < m_nAngles; ++j) {
5621 for (unsigned int k = 0; k < m_nBfields; ++k) {
5622 if (m_debug) {
5623 std::cout << m_className << "::GenerateGasTable:\n";
5624 std::cout << " E = " << eFields[i] << " V/cm, B = " << bFields[k]
5625 << " T, angle: " << bAngles[j] << " rad\n";
5626 }
5627 RunMagboltz(eFields[i], bFields[k], bAngles[j], numColl, verbose, vx,
5628 vy, vz, difl, dift, alpha, eta, vxerr, vyerr, vzerr,
5629 diflerr, difterr, alphaerr, etaerr, alphatof);
5630 tabElectronVelocityE[j][k][i] = vz;
5631 tabElectronVelocityExB[j][k][i] = vy;
5632 tabElectronVelocityB[j][k][i] = vx;
5633 tabElectronDiffLong[j][k][i] = difl;
5634 tabElectronDiffTrans[j][k][i] = dift;
5635 if (alpha > 0.) {
5636 tabElectronTownsend[j][k][i] = log(alpha);
5637 tabTownsendNoPenning[j][k][i] = log(alpha);
5638 } else {
5639 tabElectronTownsend[j][k][i] = -30.;
5640 tabTownsendNoPenning[j][k][i] = -30.;
5641 }
5642 if (eta > 0.) {
5643 tabElectronAttachment[j][k][i] = log(eta);
5644 } else {
5645 tabElectronAttachment[j][k][i] = -30.;
5646 }
5647 }
5648 }
5649 }
5650}
std::vector< ionListElement > ionisationList
Definition: MediumGas.hh:128
std::vector< std::vector< std::vector< std::vector< double > > > > tabIonRates
Definition: MediumGas.hh:110
std::vector< std::vector< std::vector< double > > > tabTownsendNoPenning
Definition: MediumGas.hh:105
std::vector< std::vector< std::vector< std::vector< double > > > > tabExcRates
Definition: MediumGas.hh:109
std::vector< excListElement > excitationList
Definition: MediumGas.hh:121
void RunMagboltz(const double e, const double b, const double btheta, const int ncoll, bool verbose, double &vx, double &vy, double &vz, double &dl, double &dt, double &alpha, double &eta, double &vxerr, double &vyerr, double &vzerr, double &dlerr, double &dterr, double &alphaerr, double &etaerr, double &alphatof)
unsigned int m_nBfields
Definition: Medium.hh:323
bool m_hasElectronDiffTrans
Definition: Medium.hh:334
bool m_hasElectronTownsend
Definition: Medium.hh:335
std::vector< double > bFields
Definition: Medium.hh:327
std::vector< std::vector< std::vector< double > > > tabElectronVelocityB
Definition: Medium.hh:338
unsigned int m_nAngles
Definition: Medium.hh:324
bool m_hasElectronVelocityB
Definition: Medium.hh:333
std::vector< double > eFields
Definition: Medium.hh:326
std::vector< std::vector< std::vector< double > > > tabElectronVelocityE
Definition: Medium.hh:336
std::vector< double > bAngles
Definition: Medium.hh:328
std::vector< std::vector< std::vector< double > > > tabElectronDiffLong
Definition: Medium.hh:339
std::vector< std::vector< std::vector< double > > > tabElectronAttachment
Definition: Medium.hh:342
unsigned int m_nEfields
Definition: Medium.hh:322
bool m_hasElectronVelocityExB
Definition: Medium.hh:333
bool m_hasIonDiffTrans
Definition: Medium.hh:363
bool m_hasIonMobility
Definition: Medium.hh:362
bool m_hasElectronDiffLong
Definition: Medium.hh:334
void InitParamArrays(const unsigned int &eRes, const unsigned int &bRes, const unsigned int &aRes, std::vector< std::vector< std::vector< double > > > &tab, const double &val)
Definition: Medium.cc:2772
bool m_hasIonDissociation
Definition: Medium.hh:364
bool m_hasIonDiffLong
Definition: Medium.hh:363
bool m_hasElectronVelocityE
Definition: Medium.hh:333
std::vector< std::vector< std::vector< double > > > tabElectronTownsend
Definition: Medium.hh:341
bool m_hasElectronAttachment
Definition: Medium.hh:335
std::vector< std::vector< std::vector< double > > > tabElectronDiffTrans
Definition: Medium.hh:340
std::vector< std::vector< std::vector< double > > > tabElectronVelocityExB
Definition: Medium.hh:337

◆ GetDeexcitationProduct()

bool Garfield::MediumMagboltz::GetDeexcitationProduct ( const int  i,
double &  t,
double &  s,
int &  type,
double &  energy 
)
virtual

Reimplemented from Garfield::Medium.

Definition at line 903 of file MediumMagboltz.cc.

904 {
905
906 if (i < 0 || i >= nDeexcitationProducts || !(useDeexcitation || usePenning))
907 return false;
908 t = dxcProducts[i].t;
909 s = dxcProducts[i].s;
910 type = dxcProducts[i].type;
911 energy = dxcProducts[i].energy;
912 return true;
913}

◆ GetElectronCollision()

bool Garfield::MediumMagboltz::GetElectronCollision ( const double  e,
int &  type,
int &  level,
double &  e1,
double &  dx,
double &  dy,
double &  dz,
int &  nion,
int &  ndxc,
int &  band 
)
virtual

Reimplemented from Garfield::Medium.

Definition at line 651 of file MediumMagboltz.cc.

654 {
655
656 // Check if the electron energy is within the currently set range.
657 if (e > eFinal && useAutoAdjust) {
658 std::cerr << m_className << "::GetElectronCollision:\n";
659 std::cerr << " Provided electron energy (" << e
660 << " eV) exceeds current energy range (" << eFinal << " eV).\n";
661 std::cerr << " Increasing energy range to " << 1.05 * e << " eV.\n";
662 SetMaxElectronEnergy(1.05 * e);
663 } else if (e <= 0.) {
664 std::cerr << m_className << "::GetElectronCollision:\n";
665 std::cerr << " Electron energy must be greater than zero.\n";
666 return false;
667 }
668
669 // If necessary, update the collision rates table.
670 if (m_isChanged) {
671 if (!Mixer()) {
672 std::cerr << m_className << "::GetElectronCollision:\n";
673 std::cerr << " Error calculating the collision rates table.\n";
674 return false;
675 }
676 m_isChanged = false;
677 }
678
679 if (m_debug && band > 0) {
680 std::cerr << m_className << "::GetElectronCollision:\n";
681 std::cerr << " Warning: unexpected band index.\n";
682 }
683
684 double angCut = 1.;
685 double angPar = 0.5;
686
687 if (e <= eHigh) {
688 // Linear binning
689 // Get the energy interval.
690 int iE = int(e / eStep);
691 if (iE >= nEnergySteps) iE = nEnergySteps - 1;
692 if (iE < 0) iE = 0;
693
694 // Sample the scattering process.
695 const double r = RndmUniform();
696 int iLow = 0;
697 int iUp = nTerms - 1;
698 if (r <= cf[iE][iLow]) {
699 level = iLow;
700 } else if (r >= cf[iE][iUp]) {
701 level = iUp;
702 } else {
703 int iMid;
704 while (iUp - iLow > 1) {
705 iMid = (iLow + iUp) >> 1;
706 if (r < cf[iE][iMid]) {
707 iUp = iMid;
708 } else {
709 iLow = iMid;
710 }
711 }
712 level = iUp;
713 }
714 // Get the angular distribution parameters.
715 angCut = scatCut[iE][level];
716 angPar = scatParameter[iE][level];
717 } else {
718 // Logarithmic binning
719 // Get the energy interval.
720 int iE = int(log(e / eHigh) / lnStep);
721 if (iE < 0) iE = 0;
722 if (iE >= nEnergyStepsLog) iE = nEnergyStepsLog - 1;
723 // Sample the scattering process.
724 const double r = RndmUniform();
725 int iLow = 0;
726 int iUp = nTerms - 1;
727 if (r <= cfLog[iE][iLow]) {
728 level = iLow;
729 } else if (r >= cfLog[iE][iUp]) {
730 level = iUp;
731 } else {
732 int iMid;
733 while (iUp - iLow > 1) {
734 iMid = (iLow + iUp) >> 1;
735 if (r < cfLog[iE][iMid]) {
736 iUp = iMid;
737 } else {
738 iLow = iMid;
739 }
740 }
741 level = iUp;
742 }
743 // Get the angular distribution parameters.
744 angCut = scatCutLog[iE][level];
745 angPar = scatParameterLog[iE][level];
746 }
747
748 // Extract the collision type.
749 type = csType[level] % nCsTypes;
750 const int igas = int(csType[level] / nCsTypes);
751 // Increase the collision counters.
752 ++nCollisions[type];
753 ++nCollisionsDetailed[level];
754
755 // Get the energy loss for this process.
756 double loss = energyLoss[level];
757 nion = ndxc = 0;
758
759 if (type == ElectronCollisionTypeIonisation) {
760 // Sample the secondary electron energy according to
761 // the Opal-Beaty-Peterson parameterisation.
762 double esec = 0.;
763 if (useOpalBeaty) {
764 // Get the splitting parameter.
765 const double w = wOpalBeaty[level];
766 esec = w * tan(RndmUniform() * atan(0.5 * (e - loss) / w));
767 // Rescaling (SST)
768 // esec = w * pow(esec / w, 0.9524);
769 } else if (useGreenSawada) {
770 const double w = gsGreenSawada[igas] * e / (e + gbGreenSawada[igas]);
771 const double esec0 =
772 tsGreenSawada[igas] - taGreenSawada[igas] / (e + tbGreenSawada[igas]);
773 const double r = RndmUniform();
774 esec = esec0 + w * tan((r - 1.) * atan(esec0 / w) +
775 r * atan((0.5 * (e - loss) - esec0) / w));
776 } else {
777 esec = RndmUniform() * (e - loss);
778 }
779 if (esec <= 0) esec = Small;
780 loss += esec;
781 ionProducts.clear();
782 // Add the secondary electron.
783 ionProd newIonProd;
784 newIonProd.type = IonProdTypeElectron;
785 newIonProd.energy = esec;
786 ionProducts.push_back(newIonProd);
787 // Add the ion.
788 newIonProd.type = IonProdTypeIon;
789 newIonProd.energy = 0.;
790 ionProducts.push_back(newIonProd);
791 nIonisationProducts = nion = 2;
792 } else if (type == ElectronCollisionTypeExcitation) {
793 // if (gas[igas] == "CH4" && loss * rgas[igas] < 13.35 && e > 12.65) {
794 // if (RndmUniform() < 0.5) {
795 // loss = 8.55 + RndmUniform() * (13.3 - 8.55);
796 // loss /= rgas[igas];
797 // } else {
798 // loss = std::max(Small, RndmGaussian(loss * rgas[igas], 1.));
799 // loss /= rgas[igas];
800 // }
801 // }
802 // Follow the de-excitation cascade (if switched on).
803 if (useDeexcitation && iDeexcitation[level] >= 0) {
804 int fLevel = 0;
805 ComputeDeexcitationInternal(iDeexcitation[level], fLevel);
806 ndxc = nDeexcitationProducts;
807 } else if (usePenning) {
808 nDeexcitationProducts = 0;
809 dxcProducts.clear();
810 // Simplified treatment of Penning ionisation.
811 // If the energy threshold of this level exceeds the
812 // ionisation potential of one of the gases,
813 // create a new electron (with probability rPenning).
814 if (energyLoss[level] * rgas[igas] > minIonPot &&
815 RndmUniform() < rPenning[level]) {
816 // The energy of the secondary electron is assumed to be given by
817 // the difference of excitation and ionisation threshold.
818 double esec = energyLoss[level] * rgas[igas] - minIonPot;
819 if (esec <= 0) esec = Small;
820 // Add the secondary electron to the list.
821 dxcProd newDxcProd;
822 newDxcProd.t = 0.;
823 newDxcProd.s = 0.;
824 if (lambdaPenning[level] > Small) {
825 // Uniform distribution within a sphere of radius lambda
826 newDxcProd.s = lambdaPenning[level] * pow(RndmUniformPos(), 1. / 3.);
827 }
828 newDxcProd.energy = esec;
829 newDxcProd.type = DxcProdTypeElectron;
830 dxcProducts.push_back(newDxcProd);
831 nDeexcitationProducts = ndxc = 1;
832 ++nPenning;
833 }
834 }
835 }
836
837 // Make sure the energy loss is smaller than the energy.
838 if (e < loss) loss = e - 0.0001;
839
840 // Determine the scattering angle.
841 double ctheta0 = 1. - 2. * RndmUniform();
842 if (useAnisotropic) {
843 switch (scatModel[level]) {
844 case 0:
845 break;
846 case 1:
847 ctheta0 = 1. - RndmUniform() * angCut;
848 if (RndmUniform() > angPar) ctheta0 = -ctheta0;
849 break;
850 case 2:
851 ctheta0 = (ctheta0 + angPar) / (1. + angPar * ctheta0);
852 break;
853 default:
854 std::cerr << m_className << "::GetElectronCollision:\n";
855 std::cerr << " Unknown scattering model. \n";
856 std::cerr << " Using isotropic distribution.\n";
857 break;
858 }
859 }
860
861 const double s1 = rgas[igas];
862 const double s2 = (s1 * s1) / (s1 - 1.);
863 const double theta0 = acos(ctheta0);
864 const double arg = std::max(1. - s1 * loss / e, Small);
865 const double d = 1. - ctheta0 * sqrt(arg);
866
867 // Update the energy.
868 e1 = std::max(e * (1. - loss / (s1 * e) - 2. * d / s2), Small);
869 double q = std::min(sqrt((e / e1) * arg) / s1, 1.);
870 const double theta = asin(q * sin(theta0));
871 double ctheta = cos(theta);
872 if (ctheta0 < 0.) {
873 const double u = (s1 - 1.) * (s1 - 1.) / arg;
874 if (ctheta0 * ctheta0 > u) ctheta = -ctheta;
875 }
876 const double stheta = sin(theta);
877 // Calculate the direction after the collision.
878 dz = std::min(dz, 1.);
879 const double argZ = sqrt(dx * dx + dy * dy);
880
881 // Azimuth is chosen at random.
882 const double phi = TwoPi * RndmUniform();
883 const double cphi = cos(phi);
884 const double sphi = sin(phi);
885
886 if (argZ == 0.) {
887 dz = ctheta;
888 dx = cphi * stheta;
889 dy = sphi * stheta;
890 } else {
891 const double a = stheta / argZ;
892 const double dz1 = dz * ctheta + argZ * stheta * sphi;
893 const double dy1 = dy * ctheta + a * (dx * cphi - dy * dz * sphi);
894 const double dx1 = dx * ctheta - a * (dy * cphi + dx * dz * sphi);
895 dz = dz1;
896 dy = dy1;
897 dx = dx1;
898 }
899
900 return true;
901}
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:431
DoubleAc asin(const DoubleAc &f)
Definition: DoubleAc.cpp:468
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:383
DoubleAc acos(const DoubleAc &f)
Definition: DoubleAc.cpp:488
bool SetMaxElectronEnergy(const double e)
double RndmUniform()
Definition: Random.hh:16
double RndmUniformPos()
Definition: Random.hh:19

◆ GetElectronCollisionRate() [1/2]

double Garfield::MediumMagboltz::GetElectronCollisionRate ( const double  e,
const int  band 
)
virtual

Reimplemented from Garfield::Medium.

Definition at line 550 of file MediumMagboltz.cc.

551 {
552
553 // Check if the electron energy is within the currently set range.
554 if (e <= 0.) {
555 std::cerr << m_className << "::GetElectronCollisionRate:\n";
556 std::cerr << " Electron energy must be greater than zero.\n";
557 return cfTot[0];
558 }
559 if (e > eFinal && useAutoAdjust) {
560 std::cerr << m_className << "::GetElectronCollisionRate:\n";
561 std::cerr << " Collision rate at " << e
562 << " eV is not included in the current table.\n";
563 std::cerr << " Increasing energy range to " << 1.05 * e << " eV.\n";
564 SetMaxElectronEnergy(1.05 * e);
565 }
566
567 // If necessary, update the collision rates table.
568 if (m_isChanged) {
569 if (!Mixer()) {
570 std::cerr << m_className << "::GetElectronCollisionRate:\n";
571 std::cerr << " Error calculating the collision rates table.\n";
572 return 0.;
573 }
574 m_isChanged = false;
575 }
576
577 if (m_debug && band > 0) {
578 std::cerr << m_className << "::GetElectronCollisionRate:\n";
579 std::cerr << " Warning: unexpected band index.\n";
580 }
581
582 // Get the energy interval.
583 int iE = 0;
584 if (e <= eHigh) {
585 // Linear binning
586 iE = int(e / eStep);
587 if (iE >= nEnergySteps) return cfTot[nEnergySteps - 1];
588 if (iE < 0) return cfTot[0];
589 return cfTot[iE];
590 }
591
592 // Logarithmic binning
593 const double eLog = log(e);
594 iE = int((eLog - eHighLog) / lnStep);
595 // Calculate the collision rate by log-log interpolation.
596 const double fmax = cfTotLog[iE];
597 const double fmin = iE == 0 ? log(cfTot[nEnergySteps - 1]) : cfTotLog[iE - 1];
598 const double emin = eHighLog + iE * lnStep;
599 const double f = fmin + (eLog - emin) * (fmax - fmin) / lnStep;
600 return exp(f);
601}
DoubleAc exp(const DoubleAc &f)
Definition: DoubleAc.cpp:376

Referenced by GetElectronCollisionRate().

◆ GetElectronCollisionRate() [2/2]

double Garfield::MediumMagboltz::GetElectronCollisionRate ( const double  e,
const int  level,
const int  band 
)

Definition at line 603 of file MediumMagboltz.cc.

604 {
605
606 // Check if the electron energy is within the currently set range.
607 if (e <= 0.) {
608 std::cerr << m_className << "::GetElectronCollisionRate:\n";
609 std::cerr << " Electron energy must be greater than zero.\n";
610 return 0.;
611 }
612
613 // Check if the level exists.
614 if (level < 0) {
615 std::cerr << m_className << "::GetElectronCollisionRate:\n";
616 std::cerr << " Level must be greater than zero.\n";
617 return 0.;
618 } else if (level >= nTerms) {
619 std::cerr << m_className << "::GetElectronCollisionRate:\n";
620 std::cerr << " Level " << level << " does not exist.\n";
621 std::cerr << " The present gas mixture has " << nTerms
622 << " cross-section terms.\n";
623 return 0.;
624 }
625
626 // Get the total scattering rate.
627 double rate = GetElectronCollisionRate(e, band);
628 // Get the energy interval.
629 int iE = 0;
630 if (e <= eHigh) {
631 // Linear binning
632 iE = int(e / eStep);
633 if (iE >= nEnergySteps) return cfTot[nEnergySteps - 1];
634 if (level == 0) {
635 rate *= cf[iE][0];
636 } else {
637 rate *= cf[iE][level] - cf[iE][level - 1];
638 }
639 } else {
640 // Logarithmic binning
641 iE = int((log(e) - eHighLog) / lnStep);
642 if (level == 0) {
643 rate *= cfLog[iE][0];
644 } else {
645 rate *= cfLog[iE][level] - cfLog[iE][level - 1];
646 }
647 }
648 return rate;
649}
double GetElectronCollisionRate(const double e, const int band)

◆ GetElectronNullCollisionRate()

double Garfield::MediumMagboltz::GetElectronNullCollisionRate ( const int  band)
virtual

Reimplemented from Garfield::Medium.

Definition at line 530 of file MediumMagboltz.cc.

530 {
531
532 // If necessary, update the collision rates table.
533 if (m_isChanged) {
534 if (!Mixer()) {
535 std::cerr << m_className << "::GetElectronNullCollisionRate:\n";
536 std::cerr << " Error calculating the collision rates table.\n";
537 return 0.;
538 }
539 m_isChanged = false;
540 }
541
542 if (m_debug && band > 0) {
543 std::cerr << m_className << "::GetElectronNullCollisionRate:\n";
544 std::cerr << " Warning: unexpected band index.\n";
545 }
546
547 return cfNull;
548}

◆ GetIonisationProduct()

bool Garfield::MediumMagboltz::GetIonisationProduct ( const int  i,
int &  type,
double &  energy 
)
virtual

Reimplemented from Garfield::Medium.

Definition at line 915 of file MediumMagboltz.cc.

916 {
917
918 if (i < 0 || i >= nIonisationProducts) {
919 std::cerr << m_className << "::GetIonisationProduct:\n";
920 std::cerr << " Index out of range.\n";
921 return false;
922 }
923
924 type = ionProducts[i].type;
925 energy = ionProducts[i].energy;
926 return true;
927}

◆ GetLevel()

bool Garfield::MediumMagboltz::GetLevel ( const int  i,
int &  ngas,
int &  type,
std::string &  descr,
double &  e 
)

Definition at line 1127 of file MediumMagboltz.cc.

1128 {
1129
1130 if (m_isChanged) {
1131 if (!Mixer()) {
1132 std::cerr << m_className << "::GetLevel:\n";
1133 std::cerr << " Error calculating the collision rates table.\n";
1134 return false;
1135 }
1136 m_isChanged = false;
1137 }
1138
1139 if (i < 0 || i >= nTerms) {
1140 std::cerr << m_className << "::GetLevel:\n";
1141 std::cerr << " Requested level (" << i << ") does not exist.\n";
1142 return false;
1143 }
1144
1145 // Collision type
1146 type = csType[i] % nCsTypes;
1147 ngas = int(csType[i] / nCsTypes);
1148 // Description (from Magboltz)
1149 descr = std::string(50, ' ');
1150 for (int j = 50; j--;) descr[j] = description[i][j];
1151 // Threshold energy
1152 e = rgas[ngas] * energyLoss[i];
1153 if (m_debug) {
1154 std::cout << m_className << "::GetLevel:\n";
1155 std::cout << " Level " << i << ": " << descr << "\n";
1156 std::cout << " Type " << type << "\n",
1157 std::cout << " Threshold energy: " << e << " eV\n";
1158 if (type == ElectronCollisionTypeExcitation && usePenning &&
1159 e > minIonPot) {
1160 std::cout << " Penning transfer coefficient: " << rPenning[i] << "\n";
1161 } else if (type == ElectronCollisionTypeExcitation && useDeexcitation) {
1162 const int idxc = iDeexcitation[i];
1163 if (idxc < 0 || idxc >= nDeexcitations) {
1164 std::cout << " Deexcitation cascade not implemented.\n";
1165 return true;
1166 }
1167 if (deexcitations[idxc].osc > 0.) {
1168 std::cout << " Oscillator strength: " << deexcitations[idxc].osc
1169 << "\n";
1170 }
1171 std::cout << " Decay channels:\n";
1172 for (int j = 0; j < deexcitations[idxc].nChannels; ++j) {
1173 if (deexcitations[idxc].type[j] == DxcTypeRad) {
1174 std::cout << " Radiative decay to ";
1175 if (deexcitations[idxc].final[j] < 0) {
1176 std::cout << "ground state: ";
1177 } else {
1178 std::cout << deexcitations[deexcitations[idxc].final[j]].label
1179 << ": ";
1180 }
1181 } else if (deexcitations[idxc].type[j] == DxcTypeCollIon) {
1182 if (deexcitations[idxc].final[j] < 0) {
1183 std::cout << " Penning ionisation: ";
1184 } else {
1185 std::cout << " Associative ionisation: ";
1186 }
1187 } else if (deexcitations[idxc].type[j] == DxcTypeCollNonIon) {
1188 if (deexcitations[idxc].final[j] >= 0) {
1189 std::cout << " Collision-induced transition to "
1190 << deexcitations[deexcitations[idxc].final[j]].label
1191 << ": ";
1192 } else {
1193 std::cout << " Loss: ";
1194 }
1195 }
1196 if (j == 0) {
1197 std::cout << std::setprecision(5) << deexcitations[idxc].p[j] * 100.
1198 << "%\n";
1199 } else {
1200 std::cout << std::setprecision(5) << (deexcitations[idxc].p[j] -
1201 deexcitations[idxc].p[j - 1]) *
1202 100. << "%\n";
1203 }
1204 }
1205 }
1206 }
1207
1208 return true;
1209}

◆ GetMaxElectronEnergy()

double Garfield::MediumMagboltz::GetMaxElectronEnergy ( ) const
inline

Definition at line 21 of file MediumMagboltz.hh.

21{ return eFinal; }

◆ GetMaxPhotonEnergy()

double Garfield::MediumMagboltz::GetMaxPhotonEnergy ( ) const
inline

Definition at line 26 of file MediumMagboltz.hh.

26{ return eFinalGamma; }

◆ GetNumberOfDeexcitationProducts()

int Garfield::MediumMagboltz::GetNumberOfDeexcitationProducts ( )
inlinevirtual

Reimplemented from Garfield::Medium.

Definition at line 88 of file MediumMagboltz.hh.

88{ return nDeexcitationProducts; }

◆ GetNumberOfElectronCollisions() [1/3]

int Garfield::MediumMagboltz::GetNumberOfElectronCollisions ( ) const

Definition at line 1092 of file MediumMagboltz.cc.

1092 {
1093
1094 int ncoll = 0;
1095 for (int j = nCsTypes; j--;) ncoll += nCollisions[j];
1096 return ncoll;
1097}

◆ GetNumberOfElectronCollisions() [2/3]

int Garfield::MediumMagboltz::GetNumberOfElectronCollisions ( const int  level) const

Definition at line 1211 of file MediumMagboltz.cc.

1211 {
1212
1213 if (level < 0 || level >= nTerms) {
1214 std::cerr << m_className << "::GetNumberOfElectronCollisions:\n";
1215 std::cerr << " Requested cross-section term (" << level
1216 << ") does not exist.\n";
1217 return 0;
1218 }
1219 return nCollisionsDetailed[level];
1220}

◆ GetNumberOfElectronCollisions() [3/3]

int Garfield::MediumMagboltz::GetNumberOfElectronCollisions ( int &  nElastic,
int &  nIonising,
int &  nAttachment,
int &  nInelastic,
int &  nExcitation,
int &  nSuperelastic 
) const

Definition at line 1099 of file MediumMagboltz.cc.

1101 {
1102
1103 nElastic = nCollisions[ElectronCollisionTypeElastic];
1104 nIonisation = nCollisions[ElectronCollisionTypeIonisation];
1105 nAttachment = nCollisions[ElectronCollisionTypeAttachment];
1106 nInelastic = nCollisions[ElectronCollisionTypeInelastic];
1107 nExcitation = nCollisions[ElectronCollisionTypeExcitation];
1108 nSuperelastic = nCollisions[ElectronCollisionTypeSuperelastic];
1109 return nElastic + nIonisation + nAttachment + nInelastic + nExcitation +
1110 nSuperelastic;
1111}

◆ GetNumberOfIonisationProducts()

int Garfield::MediumMagboltz::GetNumberOfIonisationProducts ( )
inlinevirtual

Reimplemented from Garfield::Medium.

Definition at line 85 of file MediumMagboltz.hh.

85{ return nIonisationProducts; }

◆ GetNumberOfLevels()

int Garfield::MediumMagboltz::GetNumberOfLevels ( )

Definition at line 1113 of file MediumMagboltz.cc.

1113 {
1114
1115 if (m_isChanged) {
1116 if (!Mixer()) {
1117 std::cerr << m_className << "::GetNumberOfLevels:\n";
1118 std::cerr << " Error calculating the collision rates table.\n";
1119 return 0;
1120 }
1121 m_isChanged = false;
1122 }
1123
1124 return nTerms;
1125}

◆ GetNumberOfPenningTransfers()

int Garfield::MediumMagboltz::GetNumberOfPenningTransfers ( ) const
inline

Definition at line 112 of file MediumMagboltz.hh.

112{ return nPenning; }

◆ GetNumberOfPhotonCollisions() [1/2]

int Garfield::MediumMagboltz::GetNumberOfPhotonCollisions ( ) const

Definition at line 1222 of file MediumMagboltz.cc.

1222 {
1223
1224 int ncoll = 0;
1225 for (int j = nCsTypesGamma; j--;) ncoll += nPhotonCollisions[j];
1226 return ncoll;
1227}

◆ GetNumberOfPhotonCollisions() [2/2]

int Garfield::MediumMagboltz::GetNumberOfPhotonCollisions ( int &  nElastic,
int &  nIonising,
int &  nInelastic 
) const

Definition at line 1229 of file MediumMagboltz.cc.

1230 {
1231
1232 nElastic = nPhotonCollisions[0];
1233 nIonising = nPhotonCollisions[1];
1234 nInelastic = nPhotonCollisions[2];
1235 return nElastic + nIonising + nInelastic;
1236}

◆ GetPhotonCollision()

bool Garfield::MediumMagboltz::GetPhotonCollision ( const double  e,
int &  type,
int &  level,
double &  e1,
double &  ctheta,
int &  nsec,
double &  esec 
)
virtual

Reimplemented from Garfield::Medium.

Definition at line 974 of file MediumMagboltz.cc.

976 {
977
978 if (e > eFinalGamma && useAutoAdjust) {
979 std::cerr << m_className << "::GetPhotonCollision:\n";
980 std::cerr << " Provided electron energy (" << e
981 << " eV) exceeds current energy range (" << eFinalGamma
982 << " eV).\n";
983 std::cerr << " Increasing energy range to " << 1.05 * e << " eV.\n";
984 SetMaxPhotonEnergy(1.05 * e);
985 } else if (e <= 0.) {
986 std::cerr << m_className << "::GetPhotonCollision:\n";
987 std::cerr << " Photon energy must be greater than zero.\n";
988 return false;
989 }
990
991 if (m_isChanged) {
992 if (!Mixer()) {
993 std::cerr << m_className << "::GetPhotonCollision:\n";
994 std::cerr << " Error calculating the collision rates table.\n";
995 return false;
996 }
997 m_isChanged = false;
998 }
999
1000 // Energy interval
1001 int iE = int(e / eStepGamma);
1002 if (iE >= nEnergyStepsGamma) iE = nEnergyStepsGamma - 1;
1003 if (iE < 0) iE = 0;
1004
1005 double r = cfTotGamma[iE];
1006 if (useDeexcitation && useRadTrap && nDeexcitations > 0) {
1007 int nLines = 0;
1008 std::vector<double> pLine(0);
1009 std::vector<int> iLine(0);
1010 // Loop over the excitations.
1011 for (int i = nDeexcitations; i--;) {
1012 if (deexcitations[i].cf > 0. &&
1013 fabs(e - deexcitations[i].energy) <= deexcitations[i].width) {
1014 r += deexcitations[i].cf * TMath::Voigt(e - deexcitations[i].energy,
1015 deexcitations[i].sDoppler,
1016 2 * deexcitations[i].gPressure);
1017 pLine.push_back(r);
1018 iLine.push_back(i);
1019 ++nLines;
1020 }
1021 }
1022 r *= RndmUniform();
1023 if (nLines > 0 && r >= cfTotGamma[iE]) {
1024 // Photon is absorbed by a discrete line.
1025 for (int i = 0; i < nLines; ++i) {
1026 if (r <= pLine[i]) {
1027 ++nPhotonCollisions[PhotonCollisionTypeExcitation];
1028 int fLevel = 0;
1029 ComputeDeexcitationInternal(iLine[i], fLevel);
1030 type = PhotonCollisionTypeExcitation;
1031 nsec = nDeexcitationProducts;
1032 return true;
1033 }
1034 }
1035 std::cerr << m_className << "::GetPhotonCollision:\n";
1036 std::cerr << " Random sampling of deexcitation line failed.\n";
1037 std::cerr << " Program bug!\n";
1038 return false;
1039 }
1040 } else {
1041 r *= RndmUniform();
1042 }
1043
1044 int iLow = 0;
1045 int iUp = nPhotonTerms - 1;
1046 if (r <= cfGamma[iE][iLow]) {
1047 level = iLow;
1048 } else if (r >= cfGamma[iE][iUp]) {
1049 level = iUp;
1050 } else {
1051 int iMid;
1052 while (iUp - iLow > 1) {
1053 iMid = (iLow + iUp) >> 1;
1054 if (r < cfGamma[iE][iMid]) {
1055 iUp = iMid;
1056 } else {
1057 iLow = iMid;
1058 }
1059 }
1060 level = iUp;
1061 }
1062
1063 nsec = 0;
1064 esec = e1 = 0.;
1065 type = csTypeGamma[level];
1066 // Collision type
1067 type = type % nCsTypesGamma;
1068 int ngas = int(csTypeGamma[level] / nCsTypesGamma);
1069 ++nPhotonCollisions[type];
1070 // Ionising collision
1071 if (type == 1) {
1072 esec = e - ionPot[ngas];
1073 if (esec < Small) esec = Small;
1074 nsec = 1;
1075 }
1076
1077 // Determine the scattering angle
1078 ctheta = 2 * RndmUniform() - 1.;
1079
1080 return true;
1081}
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:616
bool SetMaxPhotonEnergy(const double e)

◆ GetPhotonCollisionRate()

double Garfield::MediumMagboltz::GetPhotonCollisionRate ( const double &  e)
virtual

Reimplemented from Garfield::Medium.

Definition at line 929 of file MediumMagboltz.cc.

929 {
930
931 if (e <= 0.) {
932 std::cerr << m_className << "::GetPhotonCollisionRate:\n";
933 std::cerr << " Photon energy must be greater than zero.\n";
934 return cfTotGamma[0];
935 }
936 if (e > eFinalGamma && useAutoAdjust) {
937 std::cerr << m_className << "::GetPhotonCollisionRate:\n";
938 std::cerr << " Collision rate at " << e
939 << " eV is not included in the current table.\n";
940 std::cerr << " Increasing energy range to " << 1.05 * e << " eV.\n";
941 SetMaxPhotonEnergy(1.05 * e);
942 }
943
944 if (m_isChanged) {
945 if (!Mixer()) {
946 std::cerr << m_className << "::GetPhotonCollisionRate:\n";
947 std::cerr << " Error calculating the collision rates table.\n";
948 return 0.;
949 }
950 m_isChanged = false;
951 }
952
953 int iE = int(e / eStepGamma);
954 if (iE >= nEnergyStepsGamma) iE = nEnergyStepsGamma - 1;
955 if (iE < 0) iE = 0;
956
957 double cfSum = cfTotGamma[iE];
958 if (useDeexcitation && useRadTrap && nDeexcitations > 0) {
959 // Loop over the excitations.
960 for (int i = nDeexcitations; i--;) {
961 if (deexcitations[i].cf > 0. &&
962 fabs(e - deexcitations[i].energy) <= deexcitations[i].width) {
963 cfSum +=
964 deexcitations[i].cf * TMath::Voigt(e - deexcitations[i].energy,
965 deexcitations[i].sDoppler,
966 2 * deexcitations[i].gPressure);
967 }
968 }
969 }
970
971 return cfSum;
972}

◆ Initialise()

bool Garfield::MediumMagboltz::Initialise ( const bool  verbose = false)

Definition at line 421 of file MediumMagboltz.cc.

421 {
422
423 if (!m_isChanged) {
424 if (m_debug) {
425 std::cerr << m_className << "::Initialise:\n";
426 std::cerr << " Nothing changed.\n";
427 }
428 return true;
429 }
430 if (!Mixer(verbose)) {
431 std::cerr << m_className << "::Initialise:\n";
432 std::cerr << " Error calculating the collision rates table.\n";
433 return false;
434 }
435 m_isChanged = false;
436 return true;
437}

Referenced by GarfieldPhysics::InitializePhysics(), and PrintGas().

◆ PrintGas()

void Garfield::MediumMagboltz::PrintGas ( )

Definition at line 439 of file MediumMagboltz.cc.

439 {
440
442
443 if (m_isChanged) {
444 if (!Initialise()) return;
445 }
446
447 std::cout << m_className << "::PrintGas:\n";
448 for (int i = 0; i < nTerms; ++i) {
449 // Collision type
450 int type = csType[i] % nCsTypes;
451 int ngas = int(csType[i] / nCsTypes);
452 // Description (from Magboltz)
453 std::string descr = std::string(50, ' ');
454 for (int j = 50; j--;) descr[j] = description[i][j];
455 // Threshold energy
456 double e = rgas[ngas] * energyLoss[i];
457 std::cout << " Level " << i << ": " << descr << "\n";
458 std::cout << " Type " << type;
459 if (type == ElectronCollisionTypeElastic) {
460 std::cout << " (elastic)\n";
461 } else if (type == ElectronCollisionTypeIonisation) {
462 std::cout << " (ionisation)\n";
463 std::cout << " Ionisation threshold: " << e << " eV\n";
464 } else if (type == ElectronCollisionTypeAttachment) {
465 std::cout << " (attachment)\n";
466 } else if (type == ElectronCollisionTypeInelastic) {
467 std::cout << " (inelastic)\n";
468 std::cout << " Energy loss: " << e << " eV\n";
469 } else if (type == ElectronCollisionTypeExcitation) {
470 std::cout << " (excitation)\n";
471 std::cout << " Excitation energy: " << e << " eV\n";
472 } else if (type == ElectronCollisionTypeSuperelastic) {
473 std::cout << " (super-elastic)\n";
474 std::cout << " Energy gain: " << -e << " eV\n";
475 } else {
476 std::cout << " (unknown)\n";
477 }
478 if (type == ElectronCollisionTypeExcitation && usePenning &&
479 e > minIonPot) {
480 std::cout << " Penning transfer coefficient: " << rPenning[i]
481 << "\n";
482 } else if (type == ElectronCollisionTypeExcitation && useDeexcitation) {
483 const int idxc = iDeexcitation[i];
484 if (idxc < 0 || idxc >= nDeexcitations) {
485 std::cout << " Deexcitation cascade not implemented.\n";
486 continue;
487 }
488 if (deexcitations[idxc].osc > 0.) {
489 std::cout << " Oscillator strength: " << deexcitations[idxc].osc
490 << "\n";
491 }
492 std::cout << " Decay channels:\n";
493 for (int j = 0; j < deexcitations[idxc].nChannels; ++j) {
494 if (deexcitations[idxc].type[j] == DxcTypeRad) {
495 std::cout << " Radiative decay to ";
496 if (deexcitations[idxc].final[j] < 0) {
497 std::cout << "ground state: ";
498 } else {
499 std::cout << deexcitations[deexcitations[idxc].final[j]].label
500 << ": ";
501 }
502 } else if (deexcitations[idxc].type[j] == DxcTypeCollIon) {
503 if (deexcitations[idxc].final[j] < 0) {
504 std::cout << " Penning ionisation: ";
505 } else {
506 std::cout << " Associative ionisation: ";
507 }
508 } else if (deexcitations[idxc].type[j] == DxcTypeCollNonIon) {
509 if (deexcitations[idxc].final[j] >= 0) {
510 std::cout << " Collision-induced transition to "
511 << deexcitations[deexcitations[idxc].final[j]].label
512 << ": ";
513 } else {
514 std::cout << " Loss: ";
515 }
516 }
517 if (j == 0) {
518 std::cout << std::setprecision(5) << deexcitations[idxc].p[j] * 100.
519 << "%\n";
520 } else {
521 std::cout << std::setprecision(5) << (deexcitations[idxc].p[j] -
522 deexcitations[idxc].p[j - 1]) *
523 100. << "%\n";
524 }
525 }
526 }
527 }
528}
bool Initialise(const bool verbose=false)

◆ ResetCollisionCounters()

void Garfield::MediumMagboltz::ResetCollisionCounters ( )

Definition at line 1083 of file MediumMagboltz.cc.

1083 {
1084
1085 for (int j = nCsTypes; j--;) nCollisions[j] = 0;
1086 nCollisionsDetailed.resize(nTerms);
1087 for (int j = nTerms; j--;) nCollisionsDetailed[j] = 0;
1088 nPenning = 0;
1089 for (int j = nCsTypesGamma; j--;) nPhotonCollisions[j] = 0;
1090}

◆ RunMagboltz()

void Garfield::MediumMagboltz::RunMagboltz ( const double  e,
const double  b,
const double  btheta,
const int  ncoll,
bool  verbose,
double &  vx,
double &  vy,
double &  vz,
double &  dl,
double &  dt,
double &  alpha,
double &  eta,
double &  vxerr,
double &  vyerr,
double &  vzerr,
double &  dlerr,
double &  dterr,
double &  alphaerr,
double &  etaerr,
double &  alphatof 
)

Definition at line 5390 of file MediumMagboltz.cc.

5397 {
5398
5399 // Initialize the values.
5400 vx = vy = vz = 0.;
5401 dl = dt = 0.;
5402 alpha = eta = alphatof = 0.;
5403 vxerr = vyerr = vzerr = 0.;
5404 dlerr = dterr = 0.;
5405 alphaerr = etaerr = 0.;
5406
5407 // Set input parameters in Magboltz common blocks.
5409 Magboltz::inpt_.nStep = 4000;
5410 Magboltz::inpt_.nAniso = 2;
5411
5412 Magboltz::inpt_.tempc = m_temperature - ZeroCelsius;
5414 Magboltz::inpt_.ipen = 0;
5415 Magboltz::setp_.nmax = ncoll;
5416
5417 Magboltz::setp_.efield = e;
5418 // Convert from Tesla to kGauss.
5419 Magboltz::bfld_.bmag = bmag * 10.;
5420 // Convert from radians to degree.
5421 Magboltz::bfld_.btheta = btheta * 180. / Pi;
5422
5423 // Set the gas composition in Magboltz.
5424 for (unsigned int i = 0; i < m_nComponents; ++i) {
5425 int ng = 0;
5426 if (!GetGasNumberMagboltz(gas[i], ng)) {
5427 std::cerr << m_className << "::RunMagboltz:\n";
5428 std::cerr << " Gas " << gas[i] << " has no corresponding"
5429 << " gas number in Magboltz.\n";
5430 return;
5431 }
5432 Magboltz::gasn_.ngasn[i] = ng;
5433 Magboltz::ratio_.frac[i] = 100 * fraction[i];
5434 }
5435
5436 // Call Magboltz internal setup routine.
5438
5439 // Calculate the max. energy in the table.
5440 if (e * m_temperature / (293.15 * m_pressure) > 15) {
5441 // If E/p > 15 start with 8 eV.
5442 Magboltz::inpt_.efinal = 8.;
5443 } else {
5444 Magboltz::inpt_.efinal = 0.5;
5445 }
5446 Magboltz::setp_.estart = Magboltz::inpt_.efinal / 50.;
5447
5448 long long ielow = 1;
5449 while (ielow == 1) {
5451 if (bmag == 0. || btheta == 0. || fabs(btheta) == Pi) {
5452 Magboltz::elimit_(&ielow);
5453 } else if (btheta == HalfPi) {
5454 Magboltz::elimitb_(&ielow);
5455 } else {
5456 Magboltz::elimitc_(&ielow);
5457 }
5458 if (ielow == 1) {
5459 // Increase the max. energy.
5460 Magboltz::inpt_.efinal *= sqrt(2.);
5461 Magboltz::setp_.estart = Magboltz::inpt_.efinal / 50.;
5462 }
5463 }
5464
5465 if (m_debug || verbose) Magboltz::prnter_();
5466
5467 // Run the Monte Carlo calculation.
5468 if (bmag == 0.) {
5470 } else if (btheta == 0. || btheta == Pi) {
5472 } else if (btheta == HalfPi) {
5474 } else {
5476 }
5477 if (m_debug || verbose) Magboltz::output_();
5478
5479 // If attachment or ionisation rate is greater than sstmin,
5480 // include spatial gradients in the solution.
5481 const double sstmin = 30.;
5482 const double epscale = 760. * m_temperature / (m_pressure * 293.15);
5483 double alpp = Magboltz::ctowns_.alpha * epscale;
5484 double attp = Magboltz::ctowns_.att * epscale;
5485 bool useSST = false;
5486 if (fabs(alpp - attp) > sstmin || alpp > sstmin || attp > sstmin) {
5487 useSST = true;
5488 if (bmag == 0.) {
5490 } else if (btheta == 0. || btheta == Pi) {
5492 } else if (btheta == HalfPi) {
5494 } else {
5496 }
5497 // Calculate the (effective) TOF Townsend coefficient.
5498 double alphapt = Magboltz::tofout_.ralpha;
5499 double etapt = Magboltz::tofout_.rattof;
5500 double fc1 =
5501 1.e5 * Magboltz::tofout_.tofwr / (2. * Magboltz::tofout_.tofdl);
5502 double fc2 = 1.e12 * (alphapt - etapt) / Magboltz::tofout_.tofdl;
5503 alphatof = fc1 - sqrt(fc1 * fc1 - fc2);
5504 }
5505 if (m_debug || verbose) Magboltz::output2_();
5506
5507 // Convert to cm / ns.
5508 vx = Magboltz::vel_.wx * 1.e-9;
5509 vxerr = Magboltz::velerr_.dwx;
5510 vy = Magboltz::vel_.wy * 1.e-9;
5511 vyerr = Magboltz::velerr_.dwy;
5512 vz = Magboltz::vel_.wz * 1.e-9;
5513 vzerr = Magboltz::velerr_.dwz;
5514
5515 dt = sqrt(0.2 * Magboltz::difvel_.diftr / vz) * 1.e-4;
5516 dterr = Magboltz::diferl_.dfter;
5517 dl = sqrt(0.2 * Magboltz::difvel_.difln / vz) * 1.e-4;
5518 dlerr = Magboltz::diferl_.dfler;
5519
5520 alpha = Magboltz::ctowns_.alpha;
5521 alphaerr = Magboltz::ctwner_.alper;
5522 eta = Magboltz::ctowns_.att;
5523 etaerr = Magboltz::ctwner_.atter;
5524
5525 // Print the results.
5526 if (m_debug) {
5527 std::cout << m_className << "::RunMagboltz:\n";
5528 std::cout << " Results: \n";
5529 std::cout << " Drift velocity along E: " << std::right
5530 << std::setw(10) << std::setprecision(6) << vz << " cm/ns +/- "
5531 << std::setprecision(2) << vzerr << "%\n";
5532 std::cout << " Drift velocity along Bt: " << std::right
5533 << std::setw(10) << std::setprecision(6) << vx << " cm/ns +/- "
5534 << std::setprecision(2) << vxerr << "%\n";
5535 std::cout << " Drift velocity along ExB: " << std::right
5536 << std::setw(10) << std::setprecision(6) << vy << " cm/ns +/- "
5537 << std::setprecision(2) << vyerr << "%\n";
5538 std::cout << " Longitudinal diffusion: " << std::right
5539 << std::setw(10) << std::setprecision(6) << dl << " cm1/2 +/- "
5540 << std::setprecision(2) << dlerr << "%\n";
5541 std::cout << " Transverse diffusion: " << std::right
5542 << std::setw(10) << std::setprecision(6) << dt << " cm1/2 +/- "
5543 << std::setprecision(2) << dterr << "%\n";
5544 if (useSST) {
5545 std::cout << " Townsend coefficient (SST): " << std::right
5546 << std::setw(10) << std::setprecision(6) << alpha
5547 << " cm-1 +/- " << std::setprecision(2) << alphaerr << "%\n";
5548 std::cout << " Attachment coefficient (SST): " << std::right
5549 << std::setw(10) << std::setprecision(6) << eta << " cm-1 +/- "
5550 << std::setprecision(2) << etaerr << "%\n";
5551 std::cout << " Eff. Townsend coefficient (TOF): " << std::right
5552 << std::setw(10) << std::setprecision(6) << alphatof
5553 << " cm-1\n";
5554 } else {
5555 std::cout << " Townsend coefficient: " << std::right
5556 << std::setw(10) << std::setprecision(6) << alpha
5557 << " cm-1 +/- " << std::setprecision(2) << alphaerr << "%\n";
5558 std::cout << " Attachment coefficient: " << std::right
5559 << std::setw(10) << std::setprecision(6) << eta << " cm-1 +/- "
5560 << std::setprecision(2) << etaerr << "%\n";
5561 }
5562 }
5563}
double fraction[m_nMaxGases]
Definition: MediumGas.hh:86
struct Garfield::Magboltz::@5 ratio_
struct Garfield::Magboltz::@12 ctowns_
void elimitc_(long long *ielow)
struct Garfield::Magboltz::@13 ctwner_
struct Garfield::Magboltz::@4 gasn_
struct Garfield::Magboltz::@0 bfld_
struct Garfield::Magboltz::@7 velerr_
struct Garfield::Magboltz::@2 setp_
void elimit_(long long *ielow)
void elimitb_(long long *ielow)
struct Garfield::Magboltz::@14 tofout_
struct Garfield::Magboltz::@10 difvel_
struct Garfield::Magboltz::@6 vel_
struct Garfield::Magboltz::@11 diferl_

Referenced by GenerateGasTable().

◆ SetExcitationScalingFactor()

void Garfield::MediumMagboltz::SetExcitationScalingFactor ( const double  r,
std::string  gasname 
)

Definition at line 384 of file MediumMagboltz.cc.

385 {
386
387 if (r <= 0.) {
388 std::cerr << m_className << "::SetScalingFactor:\n";
389 std::cerr << " Incorrect value for scaling factor: " << r << "\n";
390 return;
391 }
392
393 // Get the "standard" name of this gas.
394 if (!GetGasName(gasname, gasname)) {
395 std::cerr << m_className << "::SetExcitationScalingFactor:\n";
396 std::cerr << " Unknown gas name.\n";
397 return;
398 }
399
400 // Look for this gas in the present gas mixture.
401 bool found = false;
402 for (unsigned int i = 0; i < m_nComponents; ++i) {
403 if (gas[i] == gasname) {
404 scaleExc[i] = r;
405 found = true;
406 break;
407 }
408 }
409
410 if (!found) {
411 std::cerr << m_className << "::SetExcitationScalingFactor:\n";
412 std::cerr << " Specified gas (" << gasname
413 << ") is not part of the present gas mixture.\n";
414 return;
415 }
416
417 // Make sure that the collision rate table is updated.
418 m_isChanged = true;
419}

◆ SetMaxElectronEnergy()

bool Garfield::MediumMagboltz::SetMaxElectronEnergy ( const double  e)

Definition at line 100 of file MediumMagboltz.cc.

100 {
101
102 if (e <= Small) {
103 std::cerr << m_className << "::SetMaxElectronEnergy:\n";
104 std::cerr << " Provided upper electron energy limit (" << e
105 << " eV) is too small.\n";
106 return false;
107 }
108 eFinal = e;
109
110 // Determine the energy interval size.
111 if (eFinal <= eHigh) {
112 eStep = eFinal / nEnergySteps;
113 } else {
114 eStep = eHigh / nEnergySteps;
115 }
116
117 // Set max. energy and step size also in Magboltz common block.
118 Magboltz::inpt_.efinal = eFinal;
119 Magboltz::inpt_.estep = eStep;
120
121 // Force recalculation of the scattering rates table.
122 m_isChanged = true;
123
124 return true;
125}

Referenced by GetElectronCollision(), and GetElectronCollisionRate().

◆ SetMaxPhotonEnergy()

bool Garfield::MediumMagboltz::SetMaxPhotonEnergy ( const double  e)

Definition at line 127 of file MediumMagboltz.cc.

127 {
128
129 if (e <= Small) {
130 std::cerr << m_className << "::SetMaxPhotonEnergy:\n";
131 std::cerr << " Provided upper photon energy limit (" << e
132 << " eV) is too small.\n";
133 return false;
134 }
135 eFinalGamma = e;
136
137 // Determine the energy interval size.
138 eStepGamma = eFinalGamma / nEnergyStepsGamma;
139
140 // Force recalculation of the scattering rates table.
141 m_isChanged = true;
142
143 return true;
144}

Referenced by GetPhotonCollision(), and GetPhotonCollisionRate().

◆ SetSplittingFunctionFlat()

void Garfield::MediumMagboltz::SetSplittingFunctionFlat ( )

Definition at line 171 of file MediumMagboltz.cc.

171 {
172
173 useOpalBeaty = false;
174 useGreenSawada = false;
175}

◆ SetSplittingFunctionGreenSawada()

void Garfield::MediumMagboltz::SetSplittingFunctionGreenSawada ( )

Definition at line 152 of file MediumMagboltz.cc.

152 {
153
154 useOpalBeaty = false;
155 useGreenSawada = true;
156 if (m_isChanged) return;
157
158 bool allset = true;
159 for (unsigned int i = 0; i < m_nComponents; ++i) {
160 if (!m_hasGreenSawada[i]) {
161 if (allset) {
162 std::cout << m_className << "::SetSplittingFunctionGreenSawada:\n";
163 allset = false;
164 }
165 std::cout << " Fit parameters for " << gas[i] << " not available.\n";
166 std::cout << " Opal-Beaty formula is used instead.\n";
167 }
168 }
169}

◆ SetSplittingFunctionOpalBeaty()

void Garfield::MediumMagboltz::SetSplittingFunctionOpalBeaty ( )

Definition at line 146 of file MediumMagboltz.cc.

146 {
147
148 useOpalBeaty = true;
149 useGreenSawada = false;
150}

Member Data Documentation

◆ fit3d4p

double Garfield::MediumMagboltz::fit3d4p

Definition at line 131 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dEtaC2H6

double Garfield::MediumMagboltz::fit3dEtaC2H6

Definition at line 134 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dEtaCH4

double Garfield::MediumMagboltz::fit3dEtaCH4

Definition at line 133 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dEtaCO2

double Garfield::MediumMagboltz::fit3dEtaCO2

Definition at line 132 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dQC2H6

double Garfield::MediumMagboltz::fit3dQC2H6

Definition at line 134 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dQCH4

double Garfield::MediumMagboltz::fit3dQCH4

Definition at line 133 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit3dQCO2

double Garfield::MediumMagboltz::fit3dQCO2

Definition at line 132 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit4pEtaC2H6

double Garfield::MediumMagboltz::fit4pEtaC2H6

Definition at line 136 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit4pEtaCH4

double Garfield::MediumMagboltz::fit4pEtaCH4

Definition at line 135 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fit4sEtaC2H6

double Garfield::MediumMagboltz::fit4sEtaC2H6

Definition at line 137 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fitHigh4p

double Garfield::MediumMagboltz::fitHigh4p

Definition at line 131 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().

◆ fitLineCut

double Garfield::MediumMagboltz::fitLineCut

Definition at line 138 of file MediumMagboltz.hh.

Referenced by MediumMagboltz().


The documentation for this class was generated from the following files: