Garfield++ 4.0
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 ()
 Constructor.
 
virtual ~MediumMagboltz ()
 Destructor.
 
bool SetMaxElectronEnergy (const double e)
 
double GetMaxElectronEnergy () const
 Get the highest electron energy in the table of scattering rates.
 
bool SetMaxPhotonEnergy (const double e)
 
double GetMaxPhotonEnergy () const
 Get the highest photon energy in the table of scattering rates.
 
void EnableEnergyRangeAdjustment (const bool on)
 
void EnableAnisotropicScattering (const bool on=true)
 Switch on/off anisotropic scattering (enabled by default)
 
void SetSplittingFunctionOpalBeaty ()
 Sample the secondary electron energy according to the Opal-Beaty model.
 
void SetSplittingFunctionGreenSawada ()
 Sample the secondary electron energy according to the Green-Sawada model.
 
void SetSplittingFunctionFlat ()
 Sample the secondary electron energy from a flat distribution.
 
void EnableDeexcitation ()
 Switch on (microscopic) de-excitation handling.
 
void DisableDeexcitation ()
 Switch off (microscopic) de-excitation handling.
 
void EnableRadiationTrapping ()
 Switch on discrete photoabsorption levels.
 
void DisableRadiationTrapping ()
 Switch off discrete photoabsorption levels.
 
bool EnablePenningTransfer (const double r, const double lambda) override
 
bool EnablePenningTransfer (const double r, const double lambda, std::string gasname) override
 
void DisablePenningTransfer () override
 Switch the simulation of Penning transfers off globally.
 
bool DisablePenningTransfer (std::string gasname) override
 Switch the simulation of Penning transfers off for a given component.
 
void EnableCrossSectionOutput (const bool on=true)
 Write the gas cross-section table to a file during the initialisation.
 
void SetExcitationScaling (const double r, std::string gasname)
 Multiply all excitation cross-sections by a uniform scaling factor.
 
bool Initialise (const bool verbose=false)
 
void PrintGas () override
 Print information about the present gas mixture and available data.
 
double GetElectronNullCollisionRate (const int band) override
 Get the overall null-collision rate [ns-1].
 
double GetElectronCollisionRate (const double e, const int band) override
 Get the (real) collision rate [ns-1] at a given electron energy e [eV].
 
double GetElectronCollisionRate (const double e, const unsigned int level, const int band)
 Get the collision rate [ns-1] for a specific level.
 
bool GetElectronCollision (const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, std::vector< std::pair< int, double > > &secondaries, int &ndxc, int &band) override
 Sample the collision type.
 
void ComputeDeexcitation (int iLevel, int &fLevel)
 
unsigned int GetNumberOfDeexcitationProducts () const override
 
bool GetDeexcitationProduct (const unsigned int i, double &t, double &s, int &type, double &energy) const override
 
double GetPhotonCollisionRate (const double e) override
 
bool GetPhotonCollision (const double e, int &type, int &level, double &e1, double &ctheta, int &nsec, double &esec) override
 
void ResetCollisionCounters ()
 Reset the collision counters.
 
unsigned int GetNumberOfElectronCollisions () const
 Get the total number of electron collisions.
 
unsigned int GetNumberOfElectronCollisions (unsigned int &nElastic, unsigned int &nIonising, unsigned int &nAttachment, unsigned int &nInelastic, unsigned int &nExcitation, unsigned int &nSuperelastic) const
 Get the number of collisions broken down by cross-section type.
 
unsigned int GetNumberOfLevels ()
 Get the number of cross-section terms.
 
bool GetLevel (const unsigned int i, int &ngas, int &type, std::string &descr, double &e)
 Get detailed information about a given cross-section term i.
 
unsigned int GetNumberOfElectronCollisions (const unsigned int level) const
 Get the number of collisions for a specific cross-section term.
 
unsigned int GetNumberOfPenningTransfers () const
 Get the number of Penning transfers that occured since the last reset.
 
unsigned int GetNumberOfPhotonCollisions () const
 Get the total number of photon collisions.
 
unsigned int GetNumberOfPhotonCollisions (unsigned int &nElastic, unsigned int &nIonising, unsigned int &nInelastic) const
 Get number of photon collisions by collision type.
 
void EnableThermalMotion (const bool on=true)
 
void EnableAutoEnergyLimit (const bool on=true)
 
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 &lor, double &vxerr, double &vyerr, double &vzerr, double &dlerr, double &dterr, double &alphaerr, double &etaerr, double &lorerr, double &alphatof, std::array< double, 6 > &difftens)
 
void GenerateGasTable (const int numCollisions=10, const bool verbose=true)
 
- Public Member Functions inherited from Garfield::MediumGas
 MediumGas ()
 Constructor.
 
virtual ~MediumGas ()
 Destructor.
 
bool IsGas () const override
 Is this medium a gas?
 
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.)
 Set the gas mixture.
 
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)
 Retrieve the gas mixture.
 
void GetComponent (const unsigned int i, std::string &label, double &f) override
 Get the name and fraction of a given component.
 
void SetAtomicNumber (const double z) override
 Set the effective atomic number.
 
double GetAtomicNumber () const override
 Get the effective atomic number.
 
void SetAtomicWeight (const double a) override
 Set the effective atomic weight.
 
double GetAtomicWeight () const override
 Get the effective atomic weight.
 
void SetNumberDensity (const double n) override
 Set the number density [cm-3].
 
double GetNumberDensity () const override
 Get the number density [cm-3].
 
void SetMassDensity (const double rho) override
 Set the mass density [g/cm3].
 
double GetMassDensity () const override
 Get the mass density [g/cm3].
 
bool LoadGasFile (const std::string &filename)
 Read table of gas properties (transport parameters) from file.
 
bool WriteGasFile (const std::string &filename)
 Save the present table of gas properties (transport parameters) to a file.
 
bool MergeGasFile (const std::string &filename, const bool replaceOld)
 Read table of gas properties from and merge with the existing dataset.
 
virtual bool EnablePenningTransfer (const double r, const double lambda)
 
virtual bool EnablePenningTransfer (const double r, const double lambda, std::string gasname)
 
virtual void DisablePenningTransfer ()
 Switch the simulation of Penning transfers off globally.
 
virtual bool DisablePenningTransfer (std::string gasname)
 Switch the simulation of Penning transfers off for a given component.
 
virtual void PrintGas ()
 Print information about the present gas mixture and available data.
 
bool LoadIonMobility (const std::string &filename)
 Read a table of ion mobilities as function of electric field from file.
 
bool AdjustTownsendCoefficient ()
 
void ResetTables () override
 Reset all tables of transport parameters.
 
void SetExtrapolationMethodExcitationRates (const std::string &low, const std::string &high)
 
void SetExtrapolationMethodIonisationRates (const std::string &low, const std::string &high)
 
void SetInterpolationMethodExcitationRates (const unsigned int intrp)
 
void SetInterpolationMethodIonisationRates (const unsigned int intrp)
 
double ScaleElectricField (const double e) const override
 
double UnScaleElectricField (const double e) const override
 
double ScaleDiffusion (const double d) const override
 
double ScaleDiffusionTensor (const double d) const override
 
double ScaleTownsend (const double alpha) const override
 
double ScaleAttachment (const double eta) const override
 
double ScaleLorentzAngle (const double lor) const override
 
bool GetPhotoAbsorptionCrossSection (const double e, double &sigma, const unsigned int i) override
 
- Public Member Functions inherited from Garfield::Medium
 Medium ()
 Constructor.
 
virtual ~Medium ()
 Destructor.
 
int GetId () const
 Return the id number of the class instance.
 
const std::string & GetName () const
 Get the medium name/identifier.
 
virtual bool IsGas () const
 Is this medium a gas?
 
virtual bool IsSemiconductor () const
 Is this medium a semiconductor?
 
virtual bool IsConductor () const
 Is this medium a conductor?
 
void SetTemperature (const double t)
 Set the temperature [K].
 
double GetTemperature () const
 Get the temperature [K].
 
void SetPressure (const double p)
 
double GetPressure () const
 
void SetDielectricConstant (const double eps)
 Set the relative static dielectric constant.
 
double GetDielectricConstant () const
 Get the relative static dielectric constant.
 
unsigned int GetNumberOfComponents () const
 Get number of components of the medium.
 
virtual void GetComponent (const unsigned int i, std::string &label, double &f)
 Get the name and fraction of a given component.
 
virtual void SetAtomicNumber (const double z)
 Set the effective atomic number.
 
virtual double GetAtomicNumber () const
 Get the effective atomic number.
 
virtual void SetAtomicWeight (const double a)
 Set the effective atomic weight.
 
virtual double GetAtomicWeight () const
 Get the effective atomic weight.
 
virtual void SetNumberDensity (const double n)
 Set the number density [cm-3].
 
virtual double GetNumberDensity () const
 Get the number density [cm-3].
 
virtual void SetMassDensity (const double rho)
 Set the mass density [g/cm3].
 
virtual double GetMassDensity () const
 Get the mass density [g/cm3].
 
virtual void EnableDrift (const bool on=true)
 Switch electron/ion/hole on/off.
 
virtual void EnablePrimaryIonisation (const bool on=true)
 Make the medium ionisable or non-ionisable.
 
bool IsDriftable () const
 Is charge carrier transport enabled in this medium?
 
bool IsMicroscopic () const
 Does the medium have electron scattering rates?
 
bool IsIonisable () const
 Is charge deposition by charged particles/photon enabled in this medium?
 
void SetW (const double w)
 Set the W value (average energy to produce an electron/ion or e/h pair).
 
double GetW ()
 Get the W value.
 
void SetFanoFactor (const double f)
 Set the Fano factor.
 
double GetFanoFactor ()
 Get the Fano factor.
 
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)
 Drift velocity [cm / ns].
 
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)
 Longitudinal and transverse diffusion coefficients [cm1/2].
 
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)
 Ionisation coefficient [cm-1].
 
virtual bool ElectronAttachment (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
 Attachment coefficient [cm-1].
 
virtual bool ElectronLorentzAngle (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &lor)
 Lorentz angle.
 
virtual double ElectronMobility ()
 Low-field mobility [cm2 V-1 ns-1].
 
virtual double GetElectronEnergy (const double px, const double py, const double pz, double &vx, double &vy, double &vz, const int band=0)
 Dispersion relation (energy vs. wave vector)
 
virtual void GetElectronMomentum (const double e, double &px, double &py, double &pz, int &band)
 
virtual double GetElectronNullCollisionRate (const int band=0)
 Null-collision rate [ns-1].
 
virtual double GetElectronCollisionRate (const double e, const int band=0)
 Collision rate [ns-1] for given electron energy.
 
virtual bool GetElectronCollision (const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, std::vector< std::pair< int, double > > &secondaries, int &ndxc, int &band)
 Sample the collision type. Update energy and direction vector.
 
virtual unsigned int GetNumberOfDeexcitationProducts () const
 
virtual bool GetDeexcitationProduct (const unsigned int i, double &t, double &s, int &type, double &energy) const
 
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)
 Drift velocity [cm / ns].
 
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)
 Longitudinal and transverse diffusion coefficients [cm1/2].
 
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])
 Diffusion tensor.
 
virtual bool HoleTownsend (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
 Ionisation coefficient [cm-1].
 
virtual bool HoleAttachment (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
 Attachment coefficient [cm-1].
 
virtual double HoleMobility ()
 Low-field mobility [cm2 V-1 ns-1].
 
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)
 Drift velocity [cm / ns].
 
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)
 Longitudinal and transverse diffusion coefficients [cm1/2].
 
virtual bool IonDissociation (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &diss)
 Dissociation coefficient.
 
virtual double IonMobility ()
 Low-field mobility [cm2 V-1 ns-1].
 
void SetFieldGrid (double emin, double emax, const size_t ne, bool logE, double bmin=0., double bmax=0., const size_t nb=1, double amin=HalfPi, double amax=HalfPi, const size_t na=1)
 Set the range of fields to be covered by the transport tables.
 
void SetFieldGrid (const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles)
 Set the fields and E-B angles to be used in the transport tables.
 
void GetFieldGrid (std::vector< double > &efields, std::vector< double > &bfields, std::vector< double > &angles)
 Get the fields and E-B angles used in the transport tables.
 
bool SetElectronVelocityE (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along E.
 
bool GetElectronVelocityE (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along E.
 
bool SetElectronVelocityExB (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along ExB.
 
bool GetElectronVelocityExB (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along ExB.
 
bool SetElectronVelocityB (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along Btrans.
 
bool GetElectronVelocityB (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along Btrans.
 
bool SetElectronLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dl)
 Set an entry in the table of longitudinal diffusion coefficients.
 
bool GetElectronLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dl)
 Get an entry in the table of longitudinal diffusion coefficients.
 
bool SetElectronTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dt)
 Set an entry in the table of transverse diffusion coefficients.
 
bool GetElectronTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dt)
 Get an entry in the table of transverse diffusion coefficients.
 
bool SetElectronTownsend (const size_t ie, const size_t ib, const size_t ia, const double alpha)
 Set an entry in the table of Townsend coefficients.
 
bool GetElectronTownsend (const size_t ie, const size_t ib, const size_t ia, double &alpha)
 Get an entry in the table of Townsend coefficients.
 
bool SetElectronAttachment (const size_t ie, const size_t ib, const size_t ia, const double eta)
 Set an entry in the table of attachment coefficients.
 
bool GetElectronAttachment (const size_t ie, const size_t ib, const size_t ia, double &eta)
 Get an entry in the table of attachment coefficients.
 
bool SetElectronLorentzAngle (const size_t ie, const size_t ib, const size_t ia, const double lor)
 Set an entry in the table of Lorentz angles.
 
bool GetElectronLorentzAngle (const size_t ie, const size_t ib, const size_t ia, double &lor)
 Get an entry in the table of Lorentz angles.
 
bool SetHoleVelocityE (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along E.
 
bool GetHoleVelocityE (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along E.
 
bool SetHoleVelocityExB (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along ExB.
 
bool GetHoleVelocityExB (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along ExB.
 
bool SetHoleVelocityB (const size_t ie, const size_t ib, const size_t ia, const double v)
 Set an entry in the table of drift speeds along Btrans.
 
bool GetHoleVelocityB (const size_t ie, const size_t ib, const size_t ia, double &v)
 Get an entry in the table of drift speeds along Btrans.
 
bool SetHoleLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dl)
 Set an entry in the table of longitudinal diffusion coefficients.
 
bool GetHoleLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dl)
 Get an entry in the table of longitudinal diffusion coefficients.
 
bool SetHoleTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dt)
 Set an entry in the table of transverse diffusion coefficients.
 
bool GetHoleTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dt)
 Get an entry in the table of transverse diffusion coefficients.
 
bool SetHoleTownsend (const size_t ie, const size_t ib, const size_t ia, const double alpha)
 Set an entry in the table of Townsend coefficients.
 
bool GetHoleTownsend (const size_t ie, const size_t ib, const size_t ia, double &alpha)
 Get an entry in the table of Townsend coefficients.
 
bool SetHoleAttachment (const size_t ie, const size_t ib, const size_t ia, const double eta)
 Set an entry in the table of attachment coefficients.
 
bool GetHoleAttachment (const size_t ie, const size_t ib, const size_t ia, double &eta)
 Get an entry in the table of attachment coefficients.
 
bool SetIonMobility (const std::vector< double > &fields, const std::vector< double > &mobilities)
 
bool SetIonMobility (const size_t ie, const size_t ib, const size_t ia, const double mu)
 Set an entry in the table of ion mobilities.
 
bool GetIonMobility (const size_t ie, const size_t ib, const size_t ia, double &mu)
 Get an entry in the table of ion mobilities.
 
bool SetIonLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dl)
 Set an entry in the table of longitudinal diffusion coefficients.
 
bool GetIonLongitudinalDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dl)
 Get an entry in the table of longitudinal diffusion coefficients.
 
bool SetIonTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, const double dt)
 Set an entry in the table of transverse diffusion coefficients.
 
bool GetIonTransverseDiffusion (const size_t ie, const size_t ib, const size_t ia, double &dt)
 Get an entry in the table of transverse diffusion coefficients.
 
bool SetIonDissociation (const size_t ie, const size_t ib, const size_t ia, const double diss)
 Set an entry in the table of dissociation coefficients.
 
bool GetIonDissociation (const size_t ie, const size_t ib, const size_t ia, double &diss)
 Get an entry in the table of dissociation coefficients.
 
virtual void ResetTables ()
 Reset all tables of transport parameters.
 
void ResetElectronVelocity ()
 
void ResetElectronDiffusion ()
 
void ResetElectronTownsend ()
 
void ResetElectronAttachment ()
 
void ResetElectronLorentzAngle ()
 
void ResetHoleVelocity ()
 
void ResetHoleDiffusion ()
 
void ResetHoleTownsend ()
 
void ResetHoleAttachment ()
 
void ResetIonMobility ()
 
void ResetIonDiffusion ()
 
void ResetIonDissociation ()
 
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)
 Set the degree of polynomial interpolation (usually 2).
 
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 ScaleLorentzAngle (const double lor) const
 
virtual double ScaleDissociation (const double diss) const
 
virtual bool GetOpticalDataRange (double &emin, double &emax, const unsigned int i=0)
 Get the energy range [eV] of the available optical data.
 
virtual bool GetDielectricFunction (const double e, double &eps1, double &eps2, const unsigned int i=0)
 Get the complex dielectric function at a given energy.
 
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 ()
 Switch on/off debugging messages.
 
void DisableDebugging ()
 

Additional Inherited Members

- Protected Member Functions inherited from Garfield::MediumGas
bool ReadHeader (std::ifstream &gasfile, int &version, std::bitset< 20 > &gasok, bool &is3d, std::vector< double > &mixture, std::vector< double > &efields, std::vector< double > &bfields, std::vector< double > &angles, std::vector< ExcLevel > &excLevels, std::vector< IonLevel > &ionLevels)
 
void ReadFooter (std::ifstream &gasfile, std::array< unsigned int, 13 > &extrapH, std::array< unsigned int, 13 > &extrapL, std::array< unsigned int, 13 > &interp, unsigned int &thrAlp, unsigned int &thrAtt, unsigned int &thrDis, double &ionDiffL, double &ionDiffT, double &pgas, double &tgas)
 
void ReadRecord3D (std::ifstream &gasfile, double &ve, double &vb, double &vx, double &dl, double &dt, double &alpha, double &alpha0, double &eta, double &mu, double &lor, double &dis, std::array< double, 6 > &dif, std::vector< double > &rexc, std::vector< double > &rion)
 
void ReadRecord1D (std::ifstream &gasfile, double &ve, double &vb, double &vx, double &dl, double &dt, double &alpha, double &alpha0, double &eta, double &mu, double &lor, double &dis, std::array< double, 6 > &dif, std::vector< double > &rexc, std::vector< double > &rion)
 
void InsertE (const int ie, const int ne, const int nb, const int na)
 
void InsertB (const int ib, const int ne, const int nb, const int na)
 
void InsertA (const int ia, const int ne, const int nb, const int na)
 
void ZeroRowE (const int ie, const int nb, const int na)
 
void ZeroRowB (const int ib, const int ne, const int na)
 
void ZeroRowA (const int ia, const int ne, const int nb)
 
bool GetMixture (const std::vector< double > &mixture, const int version, std::vector< std::string > &gasnames, std::vector< double > &percentages) const
 
void GetGasBits (std::bitset< 20 > &gasok) const
 
bool GetGasInfo (const std::string &gasname, double &a, double &z) const
 
std::string GetGasName (const int gasnumber, const int version) const
 
std::string GetGasName (std::string input) const
 
int GetGasNumberGasFile (const std::string &input) const
 
- Protected Member Functions inherited from Garfield::Medium
bool Velocity (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, const std::vector< std::vector< std::vector< double > > > &velE, const std::vector< std::vector< std::vector< double > > > &velB, const std::vector< std::vector< std::vector< double > > > &velX, const double q, double &vx, double &vy, double &vz) const
 
bool Diffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, const std::vector< std::vector< std::vector< double > > > &difL, const std::vector< std::vector< std::vector< double > > > &difT, double &dl, double &dt) const
 
bool Diffusion (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, const std::vector< std::vector< std::vector< std::vector< double > > > > &diff, double cov[3][3]) const
 
bool Alpha (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, const std::vector< std::vector< std::vector< double > > > &tab, unsigned int intp, const unsigned int thr, const std::pair< unsigned int, unsigned int > &extr, double &alpha) const
 
double GetAngle (const double ex, const double ey, const double ez, const double bx, const double by, const double bz, const double e, const double b) const
 
bool Interpolate (const double e, const double b, const double a, const std::vector< std::vector< std::vector< double > > > &table, double &y, const unsigned int intp, const std::pair< unsigned int, unsigned int > &extr) const
 
double Interpolate1D (const double e, const std::vector< double > &table, const std::vector< double > &fields, const unsigned int intpMeth, const std::pair< unsigned int, unsigned int > &extr) const
 
bool SetEntry (const size_t i, const size_t j, const size_t k, const std::string &fcn, std::vector< std::vector< std::vector< double > > > &tab, const double val)
 
bool GetEntry (const size_t i, const size_t j, const size_t k, const std::string &fcn, const std::vector< std::vector< std::vector< double > > > &tab, double &val) const
 
void SetExtrapolationMethod (const std::string &low, const std::string &high, std::pair< unsigned int, unsigned int > &extr, const std::string &fcn)
 
bool GetExtrapolationIndex (std::string str, unsigned int &nb) const
 
size_t SetThreshold (const std::vector< std::vector< std::vector< double > > > &tab) const
 
void Clone (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 std::pair< unsigned int, unsigned int > &extr, const double init, const std::string &label)
 
void Clone (std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const size_t n, const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles, const unsigned int intp, const std::pair< unsigned int, unsigned int > &extr, const double init, const std::string &label)
 
void Init (const size_t nE, const size_t nB, const size_t nA, std::vector< std::vector< std::vector< double > > > &tab, const double val)
 
void Init (const size_t nE, const size_t nB, const size_t nA, const size_t nT, std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const double val)
 
- Protected Attributes inherited from Garfield::MediumGas
std::array< std::string, m_nMaxGasesm_gas
 
std::array< double, m_nMaxGasesm_fraction
 
std::array< double, m_nMaxGasesm_atWeight
 
std::array< double, m_nMaxGasesm_atNum
 
bool m_usePenning = false
 
double m_rPenningGlobal = 0.
 
double m_lambdaPenningGlobal = 0.
 
std::array< double, m_nMaxGasesm_rPenningGas
 
std::array< double, m_nMaxGasesm_lambdaPenningGas
 
double m_pressureTable
 
double m_temperatureTable
 
std::vector< std::vector< std::vector< double > > > m_eAlp0
 
std::vector< std::vector< std::vector< std::vector< double > > > > m_excRates
 
std::vector< std::vector< std::vector< std::vector< double > > > > m_ionRates
 
std::vector< ExcLevelm_excLevels
 
std::vector< IonLevelm_ionLevels
 
std::pair< unsigned int, unsigned int > m_extrExc = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrIon = {0, 1}
 
unsigned int m_intpExc = 2
 
unsigned int m_intpIon = 2
 
- Protected Attributes inherited from Garfield::Medium
std::string m_className = "Medium"
 
int m_id
 
unsigned int m_nComponents = 1
 
std::string m_name = ""
 
double m_temperature = 293.15
 
double m_pressure = 760.
 
double m_epsilon = 1.
 
double m_z = 1.
 
double m_a = 0.
 
double m_density = 0.
 
double m_w = 0.
 
double m_fano = 0.
 
bool m_driftable = false
 
bool m_microscopic = false
 
bool m_ionisable = false
 
bool m_isChanged = true
 
bool m_debug = false
 
bool m_tab2d = false
 
std::vector< double > m_eFields
 
std::vector< double > m_bFields
 
std::vector< double > m_bAngles
 
std::vector< std::vector< std::vector< double > > > m_eVelE
 
std::vector< std::vector< std::vector< double > > > m_eVelX
 
std::vector< std::vector< std::vector< double > > > m_eVelB
 
std::vector< std::vector< std::vector< double > > > m_eDifL
 
std::vector< std::vector< std::vector< double > > > m_eDifT
 
std::vector< std::vector< std::vector< double > > > m_eAlp
 
std::vector< std::vector< std::vector< double > > > m_eAtt
 
std::vector< std::vector< std::vector< double > > > m_eLor
 
std::vector< std::vector< std::vector< std::vector< double > > > > m_eDifM
 
std::vector< std::vector< std::vector< double > > > m_hVelE
 
std::vector< std::vector< std::vector< double > > > m_hVelX
 
std::vector< std::vector< std::vector< double > > > m_hVelB
 
std::vector< std::vector< std::vector< double > > > m_hDifL
 
std::vector< std::vector< std::vector< double > > > m_hDifT
 
std::vector< std::vector< std::vector< double > > > m_hAlp
 
std::vector< std::vector< std::vector< double > > > m_hAtt
 
std::vector< std::vector< std::vector< std::vector< double > > > > m_hDifM
 
std::vector< std::vector< std::vector< double > > > m_iMob
 
std::vector< std::vector< std::vector< double > > > m_iDifL
 
std::vector< std::vector< std::vector< double > > > m_iDifT
 
std::vector< std::vector< std::vector< double > > > m_iDis
 
unsigned int m_eThrAlp = 0
 
unsigned int m_eThrAtt = 0
 
unsigned int m_hThrAlp = 0
 
unsigned int m_hThrAtt = 0
 
unsigned int m_iThrDis = 0
 
std::pair< unsigned int, unsigned int > m_extrVel = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrDif = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrAlp = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrAtt = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrLor = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrMob = {0, 1}
 
std::pair< unsigned int, unsigned int > m_extrDis = {0, 1}
 
unsigned int m_intpVel = 2
 
unsigned int m_intpDif = 2
 
unsigned int m_intpAlp = 2
 
unsigned int m_intpAtt = 2
 
unsigned int m_intpLor = 2
 
unsigned int m_intpMob = 2
 
unsigned int m_intpDis = 2
 
- Static Protected Attributes inherited from Garfield::MediumGas
static constexpr unsigned int m_nMaxGases = 6
 
- Static Protected Attributes inherited from Garfield::Medium
static int m_idCounter = -1
 

Detailed Description

Interface to Magboltz (version 11).

Definition at line 15 of file MediumMagboltz.hh.

Constructor & Destructor Documentation

◆ MediumMagboltz()

Garfield::MediumMagboltz::MediumMagboltz ( )

Constructor.

Definition at line 44 of file MediumMagboltz.cc.

45 : MediumGas(),
46 m_eMax(40.),
47 m_eStep(m_eMax / Magboltz::nEnergySteps),
48 m_eHigh(400.),
49 m_eHighLog(log(m_eHigh)),
50 m_lnStep(1.),
51 m_eFinalGamma(20.),
52 m_eStepGamma(m_eFinalGamma / nEnergyStepsGamma) {
53 m_className = "MediumMagboltz";
54
55 // Set physical constants in Magboltz common blocks.
56 Magboltz::cnsts_.echarg = ElementaryCharge * 1.e-15;
57 Magboltz::cnsts_.emass = ElectronMassGramme;
58 Magboltz::cnsts_.amu = AtomicMassUnit;
59 Magboltz::cnsts_.pir2 = BohrRadius * BohrRadius * Pi;
60 Magboltz::inpt_.ary = RydbergEnergy;
61
62 // Set parameters in Magboltz common blocks.
65 // Select the scattering model.
66 Magboltz::inpt_.nAniso = 2;
67 // Max. energy [eV]
68 Magboltz::inpt_.efinal = m_eMax;
69 // Energy step size [eV]
70 Magboltz::inpt_.estep = m_eStep;
71 // Temperature and pressure
72 Magboltz::inpt_.akt = BoltzmannConstant * m_temperature;
73 Magboltz::inpt_.tempc = m_temperature - ZeroCelsius;
75 // Disable Penning transfer.
76 Magboltz::inpt_.ipen = 0;
77
78 m_description.assign(Magboltz::nMaxLevels,
79 std::string(Magboltz::nCharDescr, ' '));
80
81 m_cfTot.assign(Magboltz::nEnergySteps, 0.);
82 m_cfTotLog.assign(nEnergyStepsLog, 0.);
83 m_cf.assign(Magboltz::nEnergySteps,
84 std::vector<double>(Magboltz::nMaxLevels, 0.));
85 m_cfLog.assign(nEnergyStepsLog,
86 std::vector<double>(Magboltz::nMaxLevels, 0.));
87
88 m_isChanged = true;
89
92 m_microscopic = true;
93
94 m_scaleExc.fill(1.);
95}
MediumGas()
Constructor.
Definition: MediumGas.cc:112
bool m_microscopic
Definition: Medium.hh:523
double m_pressure
Definition: Medium.hh:506
virtual void EnableDrift(const bool on=true)
Switch electron/ion/hole on/off.
Definition: Medium.hh:67
virtual void EnablePrimaryIonisation(const bool on=true)
Make the medium ionisable or non-ionisable.
Definition: Medium.hh:69
unsigned int m_nComponents
Definition: Medium.hh:500
std::string m_className
Definition: Medium.hh:493
bool m_isChanged
Definition: Medium.hh:527
double m_temperature
Definition: Medium.hh:504
constexpr unsigned int nEnergySteps
constexpr unsigned int nCharDescr
constexpr unsigned int nMaxLevels
struct Garfield::Magboltz::@1 inpt_
struct Garfield::Magboltz::@4 cnsts_

◆ ~MediumMagboltz()

virtual Garfield::MediumMagboltz::~MediumMagboltz ( )
inlinevirtual

Destructor.

Definition at line 20 of file MediumMagboltz.hh.

20{}

Member Function Documentation

◆ ComputeDeexcitation()

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

Definition at line 3106 of file MediumMagboltz.cc.

3106 {
3107 if (!m_useDeexcitation) {
3108 std::cerr << m_className << "::ComputeDeexcitation: Not enabled.\n";
3109 return;
3110 }
3111
3112 // Make sure that the tables are updated.
3113 if (m_isChanged) {
3114 if (!Mixer()) {
3115 PrintErrorMixer(m_className + "::ComputeDeexcitation");
3116 return;
3117 }
3118 m_isChanged = false;
3119 }
3120
3121 if (iLevel < 0 || iLevel >= (int)m_nTerms) {
3122 std::cerr << m_className << "::ComputeDeexcitation: Index out of range.\n";
3123 return;
3124 }
3125
3126 iLevel = m_iDeexcitation[iLevel];
3127 if (iLevel < 0 || iLevel >= (int)m_deexcitations.size()) {
3128 std::cerr << m_className << "::ComputeDeexcitation:\n"
3129 << " Level is not deexcitable.\n";
3130 return;
3131 }
3132
3133 ComputeDeexcitationInternal(iLevel, fLevel);
3134 if (fLevel >= 0 && fLevel < (int)m_deexcitations.size()) {
3135 fLevel = m_deexcitations[fLevel].level;
3136 }
3137}

◆ DisableDeexcitation()

void Garfield::MediumMagboltz::DisableDeexcitation ( )
inline

Switch off (microscopic) de-excitation handling.

Definition at line 54 of file MediumMagboltz.hh.

54{ m_useDeexcitation = false; }

◆ DisablePenningTransfer() [1/2]

void Garfield::MediumMagboltz::DisablePenningTransfer ( )
overridevirtual

Switch the simulation of Penning transfers off globally.

Reimplemented from Garfield::MediumGas.

Definition at line 286 of file MediumMagboltz.cc.

286 {
287
289 m_rPenning.fill(0.);
290 m_lambdaPenning.fill(0.);
291
292 m_usePenning = false;
293}
virtual void DisablePenningTransfer()
Switch the simulation of Penning transfers off globally.
Definition: MediumGas.cc:2431

◆ DisablePenningTransfer() [2/2]

bool Garfield::MediumMagboltz::DisablePenningTransfer ( std::string  gasname)
overridevirtual

Switch the simulation of Penning transfers off for a given component.

Reimplemented from Garfield::MediumGas.

Definition at line 295 of file MediumMagboltz.cc.

295 {
296
297 if (!MediumGas::DisablePenningTransfer(gasname)) return false;
298 // Get the "standard" name of this gas.
299 gasname = GetGasName(gasname);
300 if (gasname.empty()) return false;
301
302 // Look (again) for this gas in the present gas mixture.
303 int iGas = -1;
304 for (unsigned int i = 0; i < m_nComponents; ++i) {
305 if (m_gas[i] == gasname) {
306 iGas = i;
307 break;
308 }
309 }
310
311 if (iGas < 0) return false;
312
313 unsigned int nLevelsFound = 0;
314 for (unsigned int i = 0; i < m_nTerms; ++i) {
315 if (int(m_csType[i] / nCsTypes) == iGas) {
316 m_rPenning[i] = 0.;
317 m_lambdaPenning[i] = 0.;
318 } else {
319 if (m_csType[i] % nCsTypes == ElectronCollisionTypeExcitation &&
320 m_rPenning[i] > Small) {
321 ++nLevelsFound;
322 }
323 }
324 }
325
326 if (nLevelsFound == 0) {
327 // There are no more excitation levels with r > 0.
328 std::cout << m_className << "::DisablePenningTransfer:\n"
329 << " Penning transfer switched off for all excitations.\n";
330 m_usePenning = false;
331 }
332 return true;
333}
std::string GetGasName(const int gasnumber, const int version) const
Definition: MediumGas.cc:2718
std::array< std::string, m_nMaxGases > m_gas
Definition: MediumGas.hh:129

◆ DisableRadiationTrapping()

void Garfield::MediumMagboltz::DisableRadiationTrapping ( )
inline

Switch off discrete photoabsorption levels.

Definition at line 58 of file MediumMagboltz.hh.

58{ m_useRadTrap = false; }

◆ EnableAnisotropicScattering()

void Garfield::MediumMagboltz::EnableAnisotropicScattering ( const bool  on = true)
inline

Switch on/off anisotropic scattering (enabled by default)

Definition at line 39 of file MediumMagboltz.hh.

39 {
40 m_useAnisotropic = on;
41 m_isChanged = true;
42 }

◆ EnableAutoEnergyLimit()

void Garfield::MediumMagboltz::EnableAutoEnergyLimit ( const bool  on = true)
inline

Let Magboltz determine the upper energy limit (this is the default) or use the energy limit specified using SetMaxElectronEnergy).

Definition at line 137 of file MediumMagboltz.hh.

137{ m_autoEnergyLimit = on; }

◆ EnableCrossSectionOutput()

void Garfield::MediumMagboltz::EnableCrossSectionOutput ( const bool  on = true)
inline

Write the gas cross-section table to a file during the initialisation.

Definition at line 67 of file MediumMagboltz.hh.

67{ m_useCsOutput = on; }

◆ EnableDeexcitation()

void Garfield::MediumMagboltz::EnableDeexcitation ( )

Switch on (microscopic) de-excitation handling.

Definition at line 158 of file MediumMagboltz.cc.

158 {
159 if (m_usePenning) {
160 std::cout << m_className << "::EnableDeexcitation:\n"
161 << " Penning transfer will be switched off.\n";
162 }
163 // if (m_useRadTrap) {
164 // std::cout << " Radiation trapping is switched on.\n";
165 // } else {
166 // std::cout << " Radiation trapping is switched off.\n";
167 // }
168 m_usePenning = false;
169 m_useDeexcitation = true;
170 m_isChanged = true;
171 m_dxcProducts.clear();
172}

◆ EnableEnergyRangeAdjustment()

void Garfield::MediumMagboltz::EnableEnergyRangeAdjustment ( const bool  on)
inline

Switch on/off the automatic adjustment of the max. energy when an energy exceeding the present range is requested

Definition at line 36 of file MediumMagboltz.hh.

36{ m_useAutoAdjust = on; }

◆ EnablePenningTransfer() [1/2]

bool Garfield::MediumMagboltz::EnablePenningTransfer ( const double  r,
const double  lambda 
)
overridevirtual

Switch on simulation of Penning transfers by means of transfer probabilities, for all excitation levels in the mixture.

Parameters
rtransfer probability [0, 1]
lambdaparameter for sampling the distance of the Penning electron with respect to the excitation.

Reimplemented from Garfield::MediumGas.

Definition at line 184 of file MediumMagboltz.cc.

185 {
186
187 if (!MediumGas::EnablePenningTransfer(r, lambda)) return false;
188
189 m_rPenning.fill(0.);
190 m_lambdaPenning.fill(0.);
191
192 // Make sure that the collision rate table is updated.
193 if (m_isChanged) {
194 if (!Mixer()) {
195 PrintErrorMixer(m_className + "::EnablePenningTransfer");
196 return false;
197 }
198 m_isChanged = false;
199 }
200 unsigned int nLevelsFound = 0;
201 for (unsigned int i = 0; i < m_nTerms; ++i) {
202 if (m_csType[i] % nCsTypes == ElectronCollisionTypeExcitation) {
203 ++nLevelsFound;
204 }
205 m_rPenning[i] = m_rPenningGlobal;
206 m_lambdaPenning[i] = m_lambdaPenningGlobal;
207 }
208
209 if (nLevelsFound > 0) {
210 std::cout << m_className << "::EnablePenningTransfer:\n "
211 << "Updated Penning transfer parameters for " << nLevelsFound
212 << " excitation cross-sections.\n";
213 if (nLevelsFound != m_excLevels.size() && !m_excLevels.empty()) {
214 std::cerr << m_className << "::EnablePenningTransfer:\n Warning: "
215 << "mismatch between number of excitation cross-sections ("
216 << nLevelsFound << ")\n and number of excitation rates in "
217 << "the gas table (" << m_excLevels.size() << ").\n "
218 << "The gas table was probably calculated using a different "
219 << "version of Magboltz.\n";
220 }
221 } else {
222 std::cerr << m_className << "::EnablePenningTransfer:\n "
223 << "No excitation cross-sections in the present energy range.\n";
224 }
225
226 if (m_useDeexcitation) {
227 std::cout << m_className << "::EnablePenningTransfer:\n "
228 << "Deexcitation handling will be switched off.\n";
229 }
230 m_usePenning = true;
231 return true;
232}
double m_lambdaPenningGlobal
Definition: MediumGas.hh:140
std::vector< ExcLevel > m_excLevels
Definition: MediumGas.hh:166
virtual bool EnablePenningTransfer(const double r, const double lambda)
Definition: MediumGas.cc:2302

Referenced by GarfieldPhysics::InitializePhysics().

◆ EnablePenningTransfer() [2/2]

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

Switch on simulation of Penning transfers by means of transfer probabilities, for all excitations of a given component.

Reimplemented from Garfield::MediumGas.

Definition at line 234 of file MediumMagboltz.cc.

235 {
236
237 if (!MediumGas::EnablePenningTransfer(r, lambda, gasname)) return false;
238
239 // Get (again) the "standard" name of this gas.
240 gasname = GetGasName(gasname);
241 if (gasname.empty()) return false;
242
243 // Look (again) for this gas in the present mixture.
244 int iGas = -1;
245 for (unsigned int i = 0; i < m_nComponents; ++i) {
246 if (m_gas[i] == gasname) {
247 iGas = i;
248 break;
249 }
250 }
251
252 // Make sure that the collision rate table is updated.
253 if (m_isChanged) {
254 if (!Mixer()) {
255 PrintErrorMixer(m_className + "::EnablePenningTransfer");
256 return false;
257 }
258 m_isChanged = false;
259 }
260 unsigned int nLevelsFound = 0;
261 for (unsigned int i = 0; i < m_nTerms; ++i) {
262 if (int(m_csType[i] / nCsTypes) != iGas) continue;
263 if (m_csType[i] % nCsTypes == ElectronCollisionTypeExcitation) {
264 ++nLevelsFound;
265 }
266 m_rPenning[i] = m_rPenningGas[iGas];
267 m_lambdaPenning[i] = m_lambdaPenningGas[iGas];
268 }
269
270 if (nLevelsFound > 0) {
271 std::cout << m_className << "::EnablePenningTransfer:\n"
272 << " Penning transfer parameters for " << nLevelsFound
273 << " excitation levels set to:\n"
274 << " r = " << m_rPenningGas[iGas] << "\n"
275 << " lambda = " << m_lambdaPenningGas[iGas] << " cm\n";
276 } else {
277 std::cerr << m_className << "::EnablePenningTransfer:\n"
278 << " Specified gas (" << gasname
279 << ") has no excitation levels in the present energy range.\n";
280 }
281
282 m_usePenning = true;
283 return true;
284}
std::array< double, m_nMaxGases > m_rPenningGas
Definition: MediumGas.hh:142
std::array< double, m_nMaxGases > m_lambdaPenningGas
Definition: MediumGas.hh:144

◆ EnableRadiationTrapping()

void Garfield::MediumMagboltz::EnableRadiationTrapping ( )

Switch on discrete photoabsorption levels.

Definition at line 174 of file MediumMagboltz.cc.

174 {
175 m_useRadTrap = true;
176 if (!m_useDeexcitation) {
177 std::cout << m_className << "::EnableRadiationTrapping:\n "
178 << "Radiation trapping is enabled but de-excitation is not.\n";
179 } else {
180 m_isChanged = true;
181 }
182}

◆ EnableThermalMotion()

void Garfield::MediumMagboltz::EnableThermalMotion ( const bool  on = true)
inline

Take the thermal motion of the gas at the selected temperature into account in the calculations done by Magboltz. By the default, this feature is off (static gas at 0 K).

Definition at line 134 of file MediumMagboltz.hh.

134{ m_useGasMotion = on; }

◆ GenerateGasTable()

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

Generate a new gas table (can later be saved to file) by running Magboltz for all electric fields, magnetic fields, and angles in the currently set grid.

Definition at line 3498 of file MediumMagboltz.cc.

3498 {
3499 // Set the reference pressure and temperature.
3502
3503 // Initialize the parameter arrays.
3504 const unsigned int nEfields = m_eFields.size();
3505 const unsigned int nBfields = m_bFields.size();
3506 const unsigned int nAngles = m_bAngles.size();
3507 Init(nEfields, nBfields, nAngles, m_eVelE, 0.);
3508 Init(nEfields, nBfields, nAngles, m_eVelB, 0.);
3509 Init(nEfields, nBfields, nAngles, m_eVelX, 0.);
3510 Init(nEfields, nBfields, nAngles, m_eDifL, 0.);
3511 Init(nEfields, nBfields, nAngles, m_eDifT, 0.);
3512 Init(nEfields, nBfields, nAngles, m_eLor, 0.);
3513 Init(nEfields, nBfields, nAngles, m_eAlp, -30.);
3514 Init(nEfields, nBfields, nAngles, m_eAlp0, -30.);
3515 Init(nEfields, nBfields, nAngles, m_eAtt, -30.);
3516 Init(nEfields, nBfields, nAngles, 6, m_eDifM, 0.);
3517
3518 m_excRates.clear();
3519 m_ionRates.clear();
3520 // Retrieve the excitation and ionisation cross-sections in the gas mixture.
3521 GetExcitationIonisationLevels();
3522 std::cout << m_className << "::GenerateGasTable: Found "
3523 << m_excLevels.size() << " excitations and "
3524 << m_ionLevels.size() << " ionisations.\n";
3525 for (const auto& exc : m_excLevels) {
3526 std::cout << " " << exc.label << ", energy = " << exc.energy << " eV.\n";
3527 }
3528 for (const auto& ion : m_ionLevels) {
3529 std::cout << " " << ion.label << ", energy = " << ion.energy << " eV.\n";
3530 }
3531 if (!m_excLevels.empty()) {
3532 Init(nEfields, nBfields, nAngles, m_excLevels.size(), m_excRates, 0.);
3533 }
3534 if (!m_ionLevels.empty()) {
3535 Init(nEfields, nBfields, nAngles, m_ionLevels.size(), m_ionRates, 0.);
3536 }
3537 double vx = 0., vy = 0., vz = 0.;
3538 double difl = 0., dift = 0.;
3539 double alpha = 0., eta = 0.;
3540 double lor = 0.;
3541 double vxerr = 0., vyerr = 0., vzerr = 0.;
3542 double diflerr = 0., difterr = 0.;
3543 double alphaerr = 0., etaerr = 0.;
3544 double alphatof = 0.;
3545 double lorerr = 0.;
3546 std::array<double, 6> difftens;
3547
3548 // Run through the grid of E- and B-fields and angles.
3549 for (unsigned int i = 0; i < nEfields; ++i) {
3550 const double e = m_eFields[i];
3551 for (unsigned int j = 0; j < nAngles; ++j) {
3552 const double a = m_bAngles[j];
3553 for (unsigned int k = 0; k < nBfields; ++k) {
3554 const double b = m_bFields[k];
3555 std::cout << m_className << "::GenerateGasTable: E = " << e
3556 << " V/cm, B = " << b << " T, angle: " << a << " rad\n";
3557 RunMagboltz(e, b, a, numColl, verbose, vx, vy, vz, difl, dift, alpha,
3558 eta, lor, vxerr, vyerr, vzerr, diflerr, difterr, alphaerr,
3559 etaerr, lorerr, alphatof, difftens);
3560 m_eVelE[j][k][i] = vz;
3561 m_eVelX[j][k][i] = vy;
3562 m_eVelB[j][k][i] = vx;
3563 m_eDifL[j][k][i] = difl;
3564 m_eDifT[j][k][i] = dift;
3565 m_eLor[j][k][i] = lor;
3566 m_eAlp[j][k][i] = alpha > 0. ? log(alpha) : -30.;
3567 m_eAlp0[j][k][i] = alpha > 0. ? log(alpha) : -30.;
3568 m_eAtt[j][k][i] = eta > 0. ? log(eta) : -30.;
3569 for (unsigned int l = 0; l < 6; ++l) {
3570 m_eDifM[l][j][k][i] = difftens[l];
3571 }
3572 // Retrieve the excitation and ionisation rates.
3573 unsigned int nNonZero = 0;
3574 if (m_useGasMotion) {
3575 // Retrieve the total collision frequency and number of collisions.
3576 double ftot = 0., fel = 0., fion = 0., fatt = 0., fin = 0.;
3577 std::int64_t ntotal = 0;
3578 Magboltz::colft_(&ftot, &fel, &fion, &fatt, &fin, &ntotal);
3579 if (ntotal == 0) continue;
3580 // Convert from ps-1 to ns-1.
3581 const double scale = 1.e3 * ftot / ntotal;
3582 for (unsigned int ig = 0; ig < m_nComponents; ++ig) {
3583 const auto nL = Magboltz::larget_.last[ig];
3584 for (std::int64_t il = 0; il < nL; ++il) {
3585 if (Magboltz::larget_.iarry[il][ig] <= 0) break;
3586 // Skip levels that are not ionisations or inelastic collisions.
3587 const int cstype = (Magboltz::larget_.iarry[il][ig] - 1) % 5;
3588 if (cstype != 1 && cstype != 3) continue;
3589 // const int igas = int((Magboltz::larget_.iarry[il][ig] - 1) / 5);
3590 auto descr = GetDescription(il, ig, Magboltz::script_.dscrpt);
3591 descr = m_gas[ig] + descr;
3592 if (cstype == 3) {
3593 const unsigned int nExc = m_excLevels.size();
3594 for (unsigned int ie = 0; ie < nExc; ++ie) {
3595 if (descr != m_excLevels[ie].label) continue;
3596 const auto ncoll = Magboltz::outptt_.icoln[il][ig];
3597 m_excRates[ie][j][k][i] = scale * ncoll;
3598 if (ncoll > 0) ++nNonZero;
3599 break;
3600 }
3601 } else if (cstype == 1) {
3602 const unsigned int nIon = m_ionLevels.size();
3603 for (unsigned int ii = 0; ii < nIon; ++ii) {
3604 if (descr != m_ionLevels[ii].label) continue;
3605 const auto ncoll = Magboltz::outptt_.icoln[il][ig];
3606 m_ionRates[ii][j][k][i] = scale * ncoll;
3607 if (ncoll > 0) ++nNonZero;
3608 break;
3609 }
3610 }
3611 }
3612 }
3613 } else {
3614 // Retrieve the total collision frequency and number of collisions.
3615 double ftot = 0., fel = 0., fion = 0., fatt = 0., fin = 0.;
3616 std::int64_t ntotal = 0;
3617 Magboltz::colf_(&ftot, &fel, &fion, &fatt, &fin, &ntotal);
3618 if (ntotal == 0) continue;
3619 // Convert from ps-1 to ns-1.
3620 const double scale = 1.e3 * ftot / ntotal;
3621 for (std::int64_t il = 0; il < Magboltz::nMaxLevels; ++il) {
3622 if (Magboltz::large_.iarry[il] <= 0) break;
3623 // Skip levels that are not ionisations or inelastic collisions.
3624 const int cstype = (Magboltz::large_.iarry[il] - 1) % 5;
3625 if (cstype != 1 && cstype != 3) continue;
3626 const int igas = int((Magboltz::large_.iarry[il] - 1) / 5);
3627 std::string descr = GetDescription(il, Magboltz::scrip_.dscrpt);
3628 descr = m_gas[igas] + descr;
3629 if (cstype == 3) {
3630 const unsigned int nExc = m_excLevels.size();
3631 for (unsigned int ie = 0; ie < nExc; ++ie) {
3632 if (descr != m_excLevels[ie].label) continue;
3633 m_excRates[ie][j][k][i] = scale * Magboltz::outpt_.icoln[il];
3634 if (Magboltz::outpt_.icoln[il] > 0) ++nNonZero;
3635 break;
3636 }
3637 } else if (cstype == 1) {
3638 const unsigned int nIon = m_ionLevels.size();
3639 for (unsigned int ii = 0; ii < nIon; ++ii) {
3640 if (descr != m_ionLevels[ii].label) continue;
3641 m_ionRates[ii][j][k][i] = scale * Magboltz::outpt_.icoln[il];
3642 if (Magboltz::outpt_.icoln[il] > 0) ++nNonZero;
3643 break;
3644 }
3645 }
3646 }
3647 }
3648 if (nNonZero > 0) {
3649 std::cout << " Excitation and ionisation rates:\n";
3650 std::cout << " Level "
3651 << " Rate [ns-1]\n";
3652 const unsigned int nExc = m_excLevels.size();
3653 for (unsigned int ie = 0; ie < nExc; ++ie) {
3654 if (m_excRates[ie][j][k][i] <= 0) continue;
3655 std::cout << std::setw(60) << m_excLevels[ie].label;
3656 std::printf(" %15.8f\n", m_excRates[ie][j][k][i]);
3657 }
3658 const unsigned int nIon = m_ionLevels.size();
3659 for (unsigned int ii = 0; ii < nIon; ++ii) {
3660 if (m_ionRates[ii][j][k][i] <= 0) continue;
3661 std::cout << std::setw(60) << m_ionLevels[ii].label;
3662 std::printf(" %15.8f\n", m_ionRates[ii][j][k][i]);
3663 }
3664 }
3665 }
3666 }
3667 }
3668 // Set the threshold indices.
3671}
std::vector< std::vector< std::vector< std::vector< double > > > > m_excRates
Definition: MediumGas.hh:155
std::vector< IonLevel > m_ionLevels
Definition: MediumGas.hh:172
std::vector< std::vector< std::vector< std::vector< double > > > > m_ionRates
Definition: MediumGas.hh:156
double m_temperatureTable
Definition: MediumGas.hh:149
std::vector< std::vector< std::vector< double > > > m_eAlp0
Definition: MediumGas.hh:152
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 &lor, double &vxerr, double &vyerr, double &vzerr, double &dlerr, double &dterr, double &alphaerr, double &etaerr, double &lorerr, double &alphatof, std::array< double, 6 > &difftens)
std::vector< double > m_bFields
Definition: Medium.hh:537
std::vector< std::vector< std::vector< double > > > m_eAlp
Definition: Medium.hh:546
size_t SetThreshold(const std::vector< std::vector< std::vector< double > > > &tab) const
Definition: Medium.cc:1137
std::vector< std::vector< std::vector< double > > > m_eVelE
Definition: Medium.hh:541
std::vector< std::vector< std::vector< double > > > m_eVelX
Definition: Medium.hh:542
std::vector< std::vector< std::vector< double > > > m_eDifL
Definition: Medium.hh:544
void Init(const size_t nE, const size_t nB, const size_t nA, std::vector< std::vector< std::vector< double > > > &tab, const double val)
Definition: Medium.cc:1295
std::vector< double > m_eFields
Definition: Medium.hh:536
std::vector< std::vector< std::vector< double > > > m_eAtt
Definition: Medium.hh:547
std::vector< double > m_bAngles
Definition: Medium.hh:538
std::vector< std::vector< std::vector< double > > > m_eLor
Definition: Medium.hh:548
std::vector< std::vector< std::vector< double > > > m_eDifT
Definition: Medium.hh:545
std::vector< std::vector< std::vector< double > > > m_eVelB
Definition: Medium.hh:543
std::vector< std::vector< std::vector< std::vector< double > > > > m_eDifM
Definition: Medium.hh:550
struct Garfield::Magboltz::@11 large_
struct Garfield::Magboltz::@12 larget_
struct Garfield::Magboltz::@9 scrip_
struct Garfield::Magboltz::@7 outpt_
struct Garfield::Magboltz::@8 outptt_
void colf_(double *freq, double *freel, double *freion, double *freatt, double *frein, std::int64_t *ntotal)
struct Garfield::Magboltz::@10 script_
void colft_(double *freq, double *freel, double *freion, double *freatt, double *frein, std::int64_t *ntotal)

◆ GetDeexcitationProduct()

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

Reimplemented from Garfield::Medium.

Definition at line 815 of file MediumMagboltz.cc.

817 {
818 if (i >= m_dxcProducts.size() || !(m_useDeexcitation || m_usePenning)) {
819 return false;
820 }
821 t = m_dxcProducts[i].t;
822 s = m_dxcProducts[i].s;
823 type = m_dxcProducts[i].type;
824 energy = m_dxcProducts[i].energy;
825 return true;
826}

◆ GetElectronCollision()

bool Garfield::MediumMagboltz::GetElectronCollision ( const double  e,
int &  type,
int &  level,
double &  e1,
double &  dx,
double &  dy,
double &  dz,
std::vector< std::pair< int, double > > &  secondaries,
int &  ndxc,
int &  band 
)
overridevirtual

Sample the collision type.

Reimplemented from Garfield::Medium.

Definition at line 569 of file MediumMagboltz.cc.

572 {
573 ndxc = 0;
574 if (e <= 0.) {
575 std::cerr << m_className << "::GetElectronCollision: Invalid energy.\n";
576 return false;
577 }
578 // Check if the electron energy is within the currently set range.
579 if (e > m_eMax && m_useAutoAdjust) {
580 std::cerr << m_className << "::GetElectronCollision:\n Provided energy ("
581 << e << " eV) exceeds current energy range.\n"
582 << " Increasing energy range to " << 1.05 * e << " eV.\n";
583 SetMaxElectronEnergy(1.05 * e);
584 }
585
586 // If necessary, update the collision rates table.
587 if (m_isChanged) {
588 if (!Mixer()) {
589 PrintErrorMixer(m_className + "::GetElectronCollision");
590 return false;
591 }
592 m_isChanged = false;
593 }
594
595 if (m_debug && band > 0) {
596 std::cerr << m_className << "::GetElectronCollision: Band > 0.\n";
597 }
598
599 double angCut = 1.;
600 double angPar = 0.5;
601
602 if (e <= m_eHigh) {
603 // Linear binning
604 // Get the energy interval.
605 constexpr int iemax = Magboltz::nEnergySteps - 1;
606 const int iE = std::min(std::max(int(e / m_eStep), 0), iemax);
607
608 // Sample the scattering process.
609 const double r = RndmUniform();
610 if (r <= m_cf[iE][0]) {
611 level = 0;
612 } else if (r >= m_cf[iE][m_nTerms - 1]) {
613 level = m_nTerms - 1;
614 } else {
615 const auto begin = m_cf[iE].cbegin();
616 level = std::lower_bound(begin, begin + m_nTerms, r) - begin;
617 }
618 // Get the angular distribution parameters.
619 angCut = m_scatCut[iE][level];
620 angPar = m_scatPar[iE][level];
621 } else {
622 // Logarithmic binning
623 // Get the energy interval.
624 const int iE = std::min(std::max(int(log(e / m_eHigh) / m_lnStep), 0),
625 nEnergyStepsLog - 1);
626 // Sample the scattering process.
627 const double r = RndmUniform();
628 if (r <= m_cfLog[iE][0]) {
629 level = 0;
630 } else if (r >= m_cfLog[iE][m_nTerms - 1]) {
631 level = m_nTerms - 1;
632 } else {
633 const auto begin = m_cfLog[iE].cbegin();
634 level = std::lower_bound(begin, begin + m_nTerms, r) - begin;
635 }
636 // Get the angular distribution parameters.
637 angCut = m_scatCutLog[iE][level];
638 angPar = m_scatParLog[iE][level];
639 }
640
641 // Extract the collision type.
642 type = m_csType[level] % nCsTypes;
643 const int igas = int(m_csType[level] / nCsTypes);
644 // Increase the collision counters.
645 ++m_nCollisions[type];
646 ++m_nCollisionsDetailed[level];
647
648 // Get the energy loss for this process.
649 double loss = m_energyLoss[level];
650
651 if (type == ElectronCollisionTypeVirtual) return true;
652
653 if (type == ElectronCollisionTypeIonisation) {
654 // Sample the secondary electron energy according to
655 // the Opal-Beaty-Peterson parameterisation.
656 double esec = 0.;
657 if (e < loss) loss = e - 0.0001;
658 if (m_useOpalBeaty) {
659 // Get the splitting parameter.
660 const double w = m_wOpalBeaty[level];
661 esec = w * tan(RndmUniform() * atan(0.5 * (e - loss) / w));
662 // Rescaling (SST)
663 // esec = w * pow(esec / w, 0.9524);
664 } else if (m_useGreenSawada) {
665 const double gs = m_parGreenSawada[igas][0];
666 const double gb = m_parGreenSawada[igas][1];
667 const double w = gs * e / (e + gb);
668 const double ts = m_parGreenSawada[igas][2];
669 const double ta = m_parGreenSawada[igas][3];
670 const double tb = m_parGreenSawada[igas][4];
671 const double esec0 = ts - ta / (e + tb);
672 const double r = RndmUniform();
673 esec = esec0 +
674 w * tan((r - 1.) * atan(esec0 / w) +
675 r * atan((0.5 * (e - loss) - esec0) / w));
676 } else {
677 esec = RndmUniform() * (e - loss);
678 }
679 if (esec <= 0) esec = Small;
680 loss += esec;
681 // Add the secondary electron.
682 secondaries.emplace_back(std::make_pair(IonProdTypeElectron, esec));
683 // Add the ion.
684 secondaries.emplace_back(std::make_pair(IonProdTypeIon, 0.));
685 bool fluorescence = false;
686 if (m_yFluorescence[level] > Small) {
687 if (RndmUniform() < m_yFluorescence[level]) fluorescence = true;
688 }
689 // Add Auger and photo electrons (if any).
690 if (fluorescence) {
691 if (m_nAuger2[level] > 0) {
692 const double eav = m_eAuger2[level] / m_nAuger2[level];
693 for (unsigned int i = 0; i < m_nAuger2[level]; ++i) {
694 secondaries.emplace_back(std::make_pair(IonProdTypeElectron, eav));
695 }
696 }
697 if (m_nFluorescence[level] > 0) {
698 const double eav = m_eFluorescence[level] / m_nFluorescence[level];
699 for (unsigned int i = 0; i < m_nFluorescence[level]; ++i) {
700 secondaries.emplace_back(std::make_pair(IonProdTypeElectron, eav));
701 }
702 }
703 } else if (m_nAuger1[level] > 0) {
704 const double eav = m_eAuger1[level] / m_nAuger1[level];
705 for (unsigned int i = 0; i < m_nAuger1[level]; ++i) {
706 secondaries.emplace_back(std::make_pair(IonProdTypeElectron, eav));
707 }
708 }
709 } else if (type == ElectronCollisionTypeExcitation) {
710 // Follow the de-excitation cascade (if switched on).
711 if (m_useDeexcitation && m_iDeexcitation[level] >= 0) {
712 int fLevel = 0;
713 ComputeDeexcitationInternal(m_iDeexcitation[level], fLevel);
714 ndxc = m_dxcProducts.size();
715 } else if (m_usePenning) {
716 m_dxcProducts.clear();
717 // Simplified treatment of Penning ionisation.
718 // If the energy threshold of this level exceeds the
719 // ionisation potential of one of the gases,
720 // create a new electron (with probability rPenning).
721 if (m_debug) {
722 std::cout << m_className << "::GetElectronCollision:\n"
723 << " Level: " << level << "\n"
724 << " Ionization potential: " << m_minIonPot << "\n"
725 << " Excitation energy: " << loss * m_rgas[igas] << "\n"
726 << " Penning probability: " << m_rPenning[level] << "\n";
727 }
728 if (loss * m_rgas[igas] > m_minIonPot &&
729 RndmUniform() < m_rPenning[level]) {
730 // The energy of the secondary electron is assumed to be given by
731 // the difference of excitation and ionisation threshold.
732 double esec = loss * m_rgas[igas] - m_minIonPot;
733 if (esec <= 0) esec = Small;
734 // Add the secondary electron to the list.
735 dxcProd newDxcProd;
736 newDxcProd.t = 0.;
737 newDxcProd.s = 0.;
738 if (m_lambdaPenning[level] > Small) {
739 // Uniform distribution within a sphere of radius lambda
740 newDxcProd.s = m_lambdaPenning[level] * std::cbrt(RndmUniformPos());
741 }
742 newDxcProd.energy = esec;
743 newDxcProd.type = DxcProdTypeElectron;
744 m_dxcProducts.push_back(std::move(newDxcProd));
745 ndxc = 1;
746 ++m_nPenning;
747 }
748 }
749 }
750
751 if (e < loss) loss = e - 0.0001;
752
753 // Determine the scattering angle.
754 double ctheta0 = 1. - 2. * RndmUniform();
755 if (m_useAnisotropic) {
756 switch (m_scatModel[level]) {
757 case 0:
758 break;
759 case 1:
760 ctheta0 = 1. - RndmUniform() * angCut;
761 if (RndmUniform() > angPar) ctheta0 = -ctheta0;
762 break;
763 case 2:
764 ctheta0 = (ctheta0 + angPar) / (1. + angPar * ctheta0);
765 break;
766 default:
767 std::cerr << m_className << "::GetElectronCollision:\n"
768 << " Unknown scattering model.\n"
769 << " Using isotropic distribution.\n";
770 break;
771 }
772 }
773
774 const double s1 = m_rgas[igas];
775 const double s2 = (s1 * s1) / (s1 - 1.);
776 const double theta0 = acos(ctheta0);
777 const double arg = std::max(1. - s1 * loss / e, Small);
778 const double d = 1. - ctheta0 * sqrt(arg);
779
780 // Update the energy.
781 e1 = std::max(e * (1. - loss / (s1 * e) - 2. * d / s2), Small);
782 double q = std::min(sqrt((e / e1) * arg) / s1, 1.);
783 const double theta = asin(q * sin(theta0));
784 double ctheta = cos(theta);
785 if (ctheta0 < 0.) {
786 const double u = (s1 - 1.) * (s1 - 1.) / arg;
787 if (ctheta0 * ctheta0 > u) ctheta = -ctheta;
788 }
789 const double stheta = sin(theta);
790 // Calculate the direction after the collision.
791 dz = std::min(dz, 1.);
792 const double argZ = sqrt(dx * dx + dy * dy);
793
794 // Azimuth is chosen at random.
795 const double phi = TwoPi * RndmUniform();
796 const double cphi = cos(phi);
797 const double sphi = sin(phi);
798 if (argZ == 0.) {
799 dz = ctheta;
800 dx = cphi * stheta;
801 dy = sphi * stheta;
802 } else {
803 const double a = stheta / argZ;
804 const double dz1 = dz * ctheta + argZ * stheta * sphi;
805 const double dy1 = dy * ctheta + a * (dx * cphi - dy * dz * sphi);
806 const double dx1 = dx * ctheta - a * (dy * cphi + dx * dz * sphi);
807 dz = dz1;
808 dy = dy1;
809 dx = dx1;
810 }
811
812 return true;
813}
bool SetMaxElectronEnergy(const double e)
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
Definition: Random.hh:14
double RndmUniformPos()
Draw a random number uniformly distributed in the range (0, 1).
Definition: Random.hh:17
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:432
DoubleAc acos(const DoubleAc &f)
Definition: DoubleAc.cpp:490
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:384
DoubleAc asin(const DoubleAc &f)
Definition: DoubleAc.cpp:470
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

◆ GetElectronCollisionRate() [1/2]

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

Get the (real) collision rate [ns-1] at a given electron energy e [eV].

Reimplemented from Garfield::Medium.

Definition at line 484 of file MediumMagboltz.cc.

485 {
486 // Check if the electron energy is within the currently set range.
487 if (e <= 0.) {
488 std::cerr << m_className << "::GetElectronCollisionRate: Invalid energy.\n";
489 return m_cfTot[0];
490 }
491 if (e > m_eMax && m_useAutoAdjust) {
492 std::cerr << m_className << "::GetElectronCollisionRate:\n Rate at " << e
493 << " eV is not included in the current table.\n "
494 << "Increasing energy range to " << 1.05 * e << " eV.\n";
495 SetMaxElectronEnergy(1.05 * e);
496 }
497
498 // If necessary, update the collision rates table.
499 if (m_isChanged) {
500 if (!Mixer()) {
501 PrintErrorMixer(m_className + "::GetElectronCollisionRate");
502 return 0.;
503 }
504 m_isChanged = false;
505 }
506
507 if (m_debug && band > 0) {
508 std::cerr << m_className << "::GetElectronCollisionRate: Band > 0.\n";
509 }
510
511 // Get the energy interval.
512 if (e <= m_eHigh) {
513 // Linear binning
514 constexpr int iemax = Magboltz::nEnergySteps - 1;
515 const int iE = std::min(std::max(int(e / m_eStep), 0), iemax);
516 return m_cfTot[iE];
517 }
518
519 // Logarithmic binning
520 const double eLog = log(e);
521 int iE = int((eLog - m_eHighLog) / m_lnStep);
522 // Calculate the collision rate by log-log interpolation.
523 const double fmax = m_cfTotLog[iE];
524 const double fmin = iE == 0 ? log(m_cfTot.back()) : m_cfTotLog[iE - 1];
525 const double emin = m_eHighLog + iE * m_lnStep;
526 const double f = fmin + (eLog - emin) * (fmax - fmin) / m_lnStep;
527 return exp(f);
528}
DoubleAc exp(const DoubleAc &f)
Definition: DoubleAc.cpp:377

Referenced by GetElectronCollisionRate().

◆ GetElectronCollisionRate() [2/2]

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

Get the collision rate [ns-1] for a specific level.

Definition at line 530 of file MediumMagboltz.cc.

532 {
533 // Check if the electron energy is within the currently set range.
534 if (e <= 0.) {
535 std::cerr << m_className << "::GetElectronCollisionRate: Invalid energy.\n";
536 return 0.;
537 }
538
539 // Check if the level exists.
540 if (level >= m_nTerms) {
541 std::cerr << m_className << "::GetElectronCollisionRate: Invalid level.\n";
542 return 0.;
543 }
544
545 // Get the total scattering rate.
546 double rate = GetElectronCollisionRate(e, band);
547 // Get the energy interval.
548 if (e <= m_eHigh) {
549 // Linear binning
550 constexpr int iemax = Magboltz::nEnergySteps - 1;
551 const int iE = std::min(std::max(int(e / m_eStep), 0), iemax);
552 if (level == 0) {
553 rate *= m_cf[iE][0];
554 } else {
555 rate *= m_cf[iE][level] - m_cf[iE][level - 1];
556 }
557 } else {
558 // Logarithmic binning
559 const int iE = int((log(e) - m_eHighLog) / m_lnStep);
560 if (level == 0) {
561 rate *= m_cfLog[iE][0];
562 } else {
563 rate *= m_cfLog[iE][level] - m_cfLog[iE][level - 1];
564 }
565 }
566 return rate;
567}
double GetElectronCollisionRate(const double e, const int band) override
Get the (real) collision rate [ns-1] at a given electron energy e [eV].

◆ GetElectronNullCollisionRate()

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

Get the overall null-collision rate [ns-1].

Reimplemented from Garfield::Medium.

Definition at line 467 of file MediumMagboltz.cc.

467 {
468 // If necessary, update the collision rates table.
469 if (m_isChanged) {
470 if (!Mixer()) {
471 PrintErrorMixer(m_className + "::GetElectronNullCollisionRate");
472 return 0.;
473 }
474 m_isChanged = false;
475 }
476
477 if (m_debug && band > 0) {
478 std::cerr << m_className << "::GetElectronNullCollisionRate: Band > 0.\n";
479 }
480
481 return m_cfNull;
482}

◆ GetLevel()

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

Get detailed information about a given cross-section term i.

Definition at line 995 of file MediumMagboltz.cc.

996 {
997 if (m_isChanged) {
998 if (!Mixer()) {
999 PrintErrorMixer(m_className + "::GetLevel");
1000 return false;
1001 }
1002 m_isChanged = false;
1003 }
1004
1005 if (i >= m_nTerms) {
1006 std::cerr << m_className << "::GetLevel: Index out of range.\n";
1007 return false;
1008 }
1009
1010 // Collision type
1011 type = m_csType[i] % nCsTypes;
1012 ngas = int(m_csType[i] / nCsTypes);
1013 // Description (from Magboltz)
1014 descr = m_description[i];
1015 // Threshold energy
1016 e = m_rgas[ngas] * m_energyLoss[i];
1017 if (m_debug) {
1018 std::cout << m_className << "::GetLevel:\n"
1019 << " Level " << i << ": " << descr << "\n"
1020 << " Type " << type << "\n"
1021 << " Threshold energy: " << e << " eV\n";
1022 if (type == ElectronCollisionTypeExcitation && m_usePenning &&
1023 e > m_minIonPot) {
1024 std::cout << " Penning transfer coefficient: " << m_rPenning[i]
1025 << "\n";
1026 } else if (type == ElectronCollisionTypeExcitation && m_useDeexcitation) {
1027 const int idxc = m_iDeexcitation[i];
1028 if (idxc < 0 || idxc >= (int)m_deexcitations.size()) {
1029 std::cout << " Deexcitation cascade not implemented.\n";
1030 return true;
1031 }
1032 const auto& dxc = m_deexcitations[idxc];
1033 if (dxc.osc > 0.) {
1034 std::cout << " Oscillator strength: " << dxc.osc << "\n";
1035 }
1036 std::cout << " Decay channels:\n";
1037 const int nChannels = dxc.type.size();
1038 for (int j = 0; j < nChannels; ++j) {
1039 if (dxc.type[j] == DxcTypeRad) {
1040 std::cout << " Radiative decay to ";
1041 if (dxc.final[j] < 0) {
1042 std::cout << "ground state: ";
1043 } else {
1044 std::cout << m_deexcitations[dxc.final[j]].label << ": ";
1045 }
1046 } else if (dxc.type[j] == DxcTypeCollIon) {
1047 if (dxc.final[j] < 0) {
1048 std::cout << " Penning ionisation: ";
1049 } else {
1050 std::cout << " Associative ionisation: ";
1051 }
1052 } else if (dxc.type[j] == DxcTypeCollNonIon) {
1053 if (dxc.final[j] >= 0) {
1054 std::cout << " Collision-induced transition to "
1055 << m_deexcitations[dxc.final[j]].label << ": ";
1056 } else {
1057 std::cout << " Loss: ";
1058 }
1059 }
1060 const double br = j == 0 ? dxc.p[j] : dxc.p[j] - dxc.p[j - 1];
1061 std::cout << std::setprecision(5) << br * 100. << "%\n";
1062 }
1063 }
1064 }
1065
1066 return true;
1067}

◆ GetMaxElectronEnergy()

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

Get the highest electron energy in the table of scattering rates.

Definition at line 26 of file MediumMagboltz.hh.

26{ return m_eMax; }

◆ GetMaxPhotonEnergy()

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

Get the highest photon energy in the table of scattering rates.

Definition at line 32 of file MediumMagboltz.hh.

32{ return m_eFinalGamma; }

◆ GetNumberOfDeexcitationProducts()

unsigned int Garfield::MediumMagboltz::GetNumberOfDeexcitationProducts ( ) const
inlineoverridevirtual

Reimplemented from Garfield::Medium.

Definition at line 92 of file MediumMagboltz.hh.

92 {
93 return m_dxcProducts.size();
94 }

◆ GetNumberOfElectronCollisions() [1/3]

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

Get the total number of electron collisions.

Definition at line 965 of file MediumMagboltz.cc.

965 {
966 return std::accumulate(std::begin(m_nCollisions), std::end(m_nCollisions), 0);
967}

◆ GetNumberOfElectronCollisions() [2/3]

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

Get the number of collisions for a specific cross-section term.

Definition at line 1069 of file MediumMagboltz.cc.

1070 {
1071 if (level >= m_nTerms) {
1072 std::cerr << m_className << "::GetNumberOfElectronCollisions: "
1073 << "Level " << level << " does not exist.\n";
1074 return 0;
1075 }
1076 return m_nCollisionsDetailed[level];
1077}

◆ GetNumberOfElectronCollisions() [3/3]

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

Get the number of collisions broken down by cross-section type.

Definition at line 969 of file MediumMagboltz.cc.

972 {
973 nElastic = m_nCollisions[ElectronCollisionTypeElastic];
974 nIonisation = m_nCollisions[ElectronCollisionTypeIonisation];
975 nAttachment = m_nCollisions[ElectronCollisionTypeAttachment];
976 nInelastic = m_nCollisions[ElectronCollisionTypeInelastic];
977 nExcitation = m_nCollisions[ElectronCollisionTypeExcitation];
978 nSuperelastic = m_nCollisions[ElectronCollisionTypeSuperelastic];
979 return nElastic + nIonisation + nAttachment + nInelastic + nExcitation +
980 nSuperelastic;
981}

◆ GetNumberOfLevels()

unsigned int Garfield::MediumMagboltz::GetNumberOfLevels ( )

Get the number of cross-section terms.

Definition at line 983 of file MediumMagboltz.cc.

983 {
984 if (m_isChanged) {
985 if (!Mixer()) {
986 PrintErrorMixer(m_className + "::GetNumberOfLevels");
987 return 0;
988 }
989 m_isChanged = false;
990 }
991
992 return m_nTerms;
993}

◆ GetNumberOfPenningTransfers()

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

Get the number of Penning transfers that occured since the last reset.

Definition at line 122 of file MediumMagboltz.hh.

122{ return m_nPenning; }

◆ GetNumberOfPhotonCollisions() [1/2]

unsigned int Garfield::MediumMagboltz::GetNumberOfPhotonCollisions ( ) const

Get the total number of photon collisions.

Definition at line 1079 of file MediumMagboltz.cc.

1079 {
1080 return std::accumulate(std::begin(m_nPhotonCollisions),
1081 std::end(m_nPhotonCollisions), 0);
1082}

◆ GetNumberOfPhotonCollisions() [2/2]

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

Get number of photon collisions by collision type.

Definition at line 1084 of file MediumMagboltz.cc.

1086 {
1087 nElastic = m_nPhotonCollisions[0];
1088 nIonising = m_nPhotonCollisions[1];
1089 nInelastic = m_nPhotonCollisions[2];
1090 return nElastic + nIonising + nInelastic;
1091}

◆ GetPhotonCollision()

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

Reimplemented from Garfield::Medium.

Definition at line 865 of file MediumMagboltz.cc.

867 {
868 if (e <= 0.) {
869 std::cerr << m_className << "::GetPhotonCollision: Invalid energy.\n";
870 return false;
871 }
872 if (e > m_eFinalGamma && m_useAutoAdjust) {
873 std::cerr << m_className << "::GetPhotonCollision:\n Provided energy ("
874 << e << " eV) exceeds current energy range.\n"
875 << " Increasing energy range to " << 1.05 * e << " eV.\n";
876 SetMaxPhotonEnergy(1.05 * e);
877 }
878
879 if (m_isChanged) {
880 if (!Mixer()) {
881 PrintErrorMixer(m_className + "::GetPhotonCollision");
882 return false;
883 }
884 m_isChanged = false;
885 }
886
887 // Energy interval
888 const int iE =
889 std::min(std::max(int(e / m_eStepGamma), 0), nEnergyStepsGamma - 1);
890
891 double r = m_cfTotGamma[iE];
892 if (m_useDeexcitation && m_useRadTrap && !m_deexcitations.empty()) {
893 int nLines = 0;
894 std::vector<double> pLine(0);
895 std::vector<int> iLine(0);
896 // Loop over the excitations.
897 const unsigned int nDeexcitations = m_deexcitations.size();
898 for (unsigned int i = 0; i < nDeexcitations; ++i) {
899 const auto& dxc = m_deexcitations[i];
900 if (dxc.cf > 0. && fabs(e - dxc.energy) <= dxc.width) {
901 r += dxc.cf *
902 TMath::Voigt(e - dxc.energy, dxc.sDoppler, 2 * dxc.gPressure);
903 pLine.push_back(r);
904 iLine.push_back(i);
905 ++nLines;
906 }
907 }
908 r *= RndmUniform();
909 if (nLines > 0 && r >= m_cfTotGamma[iE]) {
910 // Photon is absorbed by a discrete line.
911 for (int i = 0; i < nLines; ++i) {
912 if (r <= pLine[i]) {
913 ++m_nPhotonCollisions[PhotonCollisionTypeExcitation];
914 int fLevel = 0;
915 ComputeDeexcitationInternal(iLine[i], fLevel);
916 type = PhotonCollisionTypeExcitation;
917 nsec = m_dxcProducts.size();
918 return true;
919 }
920 }
921 std::cerr << m_className << "::GetPhotonCollision:\n";
922 std::cerr << " Random sampling of deexcitation line failed.\n";
923 std::cerr << " Program bug!\n";
924 return false;
925 }
926 } else {
927 r *= RndmUniform();
928 }
929
930 if (r <= m_cfGamma[iE][0]) {
931 level = 0;
932 } else if (r >= m_cfGamma[iE][m_nPhotonTerms - 1]) {
933 level = m_nPhotonTerms - 1;
934 } else {
935 const auto begin = m_cfGamma[iE].cbegin();
936 level = std::lower_bound(begin, begin + m_nPhotonTerms, r) - begin;
937 }
938
939 nsec = 0;
940 esec = e1 = 0.;
941 type = csTypeGamma[level];
942 // Collision type
943 type = type % nCsTypesGamma;
944 int ngas = int(csTypeGamma[level] / nCsTypesGamma);
945 ++m_nPhotonCollisions[type];
946 // Ionising collision
947 if (type == 1) {
948 esec = std::max(e - m_ionPot[ngas], Small);
949 nsec = 1;
950 }
951
952 // Determine the scattering angle
953 ctheta = 2 * RndmUniform() - 1.;
954
955 return true;
956}
bool SetMaxPhotonEnergy(const double e)
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

◆ GetPhotonCollisionRate()

double Garfield::MediumMagboltz::GetPhotonCollisionRate ( const double  e)
overridevirtual

Reimplemented from Garfield::Medium.

Definition at line 828 of file MediumMagboltz.cc.

828 {
829 if (e <= 0.) {
830 std::cerr << m_className << "::GetPhotonCollisionRate: Invalid energy.\n";
831 return m_cfTotGamma[0];
832 }
833 if (e > m_eFinalGamma && m_useAutoAdjust) {
834 std::cerr << m_className << "::GetPhotonCollisionRate:\n Rate at " << e
835 << " eV is not included in the current table.\n"
836 << " Increasing energy range to " << 1.05 * e << " eV.\n";
837 SetMaxPhotonEnergy(1.05 * e);
838 }
839
840 if (m_isChanged) {
841 if (!Mixer()) {
842 PrintErrorMixer(m_className + "::GetPhotonCollisionRate");
843 return 0.;
844 }
845 m_isChanged = false;
846 }
847
848 const int iE =
849 std::min(std::max(int(e / m_eStepGamma), 0), nEnergyStepsGamma - 1);
850
851 double cfSum = m_cfTotGamma[iE];
852 if (m_useDeexcitation && m_useRadTrap && !m_deexcitations.empty()) {
853 // Loop over the excitations.
854 for (const auto& dxc : m_deexcitations) {
855 if (dxc.cf > 0. && fabs(e - dxc.energy) <= dxc.width) {
856 cfSum += dxc.cf *
857 TMath::Voigt(e - dxc.energy, dxc.sDoppler, 2 * dxc.gPressure);
858 }
859 }
860 }
861
862 return cfSum;
863}

◆ Initialise()

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

Initialise the table of scattering rates (called internally when a collision rate is requested and the gas mixture or other parameters have changed).

Definition at line 369 of file MediumMagboltz.cc.

369 {
370 if (!m_isChanged) {
371 if (m_debug) {
372 std::cerr << m_className << "::Initialise: Nothing changed.\n";
373 }
374 return true;
375 }
376 if (!Mixer(verbose)) {
377 PrintErrorMixer(m_className + "::Initialise");
378 return false;
379 }
380 m_isChanged = false;
381 return true;
382}

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

◆ PrintGas()

void Garfield::MediumMagboltz::PrintGas ( )
overridevirtual

Print information about the present gas mixture and available data.

Reimplemented from Garfield::MediumGas.

Definition at line 384 of file MediumMagboltz.cc.

384 {
386
387 if (m_isChanged) {
388 if (!Initialise()) return;
389 }
390
391 std::cout << " Electron cross-sections:\n";
392 int igas = -1;
393 for (unsigned int i = 0; i < m_nTerms; ++i) {
394 // Collision type
395 int type = m_csType[i] % nCsTypes;
396 if (igas != int(m_csType[i] / nCsTypes)) {
397 igas = int(m_csType[i] / nCsTypes);
398 std::cout << " " << m_gas[igas] << "\n";
399 }
400 // Description (from Magboltz)
401 // Threshold energy
402 double e = m_rgas[igas] * m_energyLoss[i];
403 std::cout << " Level " << i << ": " << m_description[i] << "\n";
404 std::cout << " Type " << type;
405 if (type == ElectronCollisionTypeElastic) {
406 std::cout << " (elastic)\n";
407 } else if (type == ElectronCollisionTypeIonisation) {
408 std::cout << " (ionisation). Ionisation threshold: " << e << " eV.\n";
409 } else if (type == ElectronCollisionTypeAttachment) {
410 std::cout << " (attachment)\n";
411 } else if (type == ElectronCollisionTypeInelastic) {
412 std::cout << " (inelastic). Energy loss: " << e << " eV.\n";
413 } else if (type == ElectronCollisionTypeExcitation) {
414 std::cout << " (excitation). Excitation energy: " << e << " eV.\n";
415 } else if (type == ElectronCollisionTypeSuperelastic) {
416 std::cout << " (super-elastic). Energy gain: " << -e << " eV.\n";
417 } else if (type == ElectronCollisionTypeVirtual) {
418 std::cout << " (virtual)\n";
419 } else {
420 std::cout << " (unknown)\n";
421 }
422 if (type == ElectronCollisionTypeExcitation && m_usePenning &&
423 e > m_minIonPot) {
424 std::cout << " Penning transfer coefficient: "
425 << m_rPenning[i] << "\n";
426 } else if (type == ElectronCollisionTypeExcitation && m_useDeexcitation) {
427 const int idxc = m_iDeexcitation[i];
428 if (idxc < 0 || idxc >= (int)m_deexcitations.size()) {
429 std::cout << " Deexcitation cascade not implemented.\n";
430 continue;
431 }
432 const auto& dxc = m_deexcitations[idxc];
433 if (dxc.osc > 0.) {
434 std::cout << " Oscillator strength: " << dxc.osc << "\n";
435 }
436 std::cout << " Decay channels:\n";
437 const int nChannels = dxc.type.size();
438 for (int j = 0; j < nChannels; ++j) {
439 if (dxc.type[j] == DxcTypeRad) {
440 std::cout << " Radiative decay to ";
441 if (dxc.final[j] < 0) {
442 std::cout << "ground state: ";
443 } else {
444 std::cout << m_deexcitations[dxc.final[j]].label << ": ";
445 }
446 } else if (dxc.type[j] == DxcTypeCollIon) {
447 if (dxc.final[j] < 0) {
448 std::cout << " Penning ionisation: ";
449 } else {
450 std::cout << " Associative ionisation: ";
451 }
452 } else if (dxc.type[j] == DxcTypeCollNonIon) {
453 if (dxc.final[j] >= 0) {
454 std::cout << " Collision-induced transition to "
455 << m_deexcitations[dxc.final[j]].label << ": ";
456 } else {
457 std::cout << " Loss: ";
458 }
459 }
460 const double br = j == 0 ? dxc.p[j] : dxc.p[j] - dxc.p[j - 1];
461 std::cout << std::setprecision(5) << br * 100. << "%\n";
462 }
463 }
464 }
465}
virtual void PrintGas()
Print information about the present gas mixture and available data.
Definition: MediumGas.cc:2072
bool Initialise(const bool verbose=false)

◆ ResetCollisionCounters()

void Garfield::MediumMagboltz::ResetCollisionCounters ( )

Reset the collision counters.

Definition at line 958 of file MediumMagboltz.cc.

958 {
959 m_nCollisions.fill(0);
960 m_nCollisionsDetailed.assign(m_nTerms, 0);
961 m_nPenning = 0;
962 m_nPhotonCollisions.fill(0);
963}

◆ 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 &  lor,
double &  vxerr,
double &  vyerr,
double &  vzerr,
double &  dlerr,
double &  dterr,
double &  alphaerr,
double &  etaerr,
double &  lorerr,
double &  alphatof,
std::array< double, 6 > &  difftens 
)

Run Magboltz for a given electric field, magnetic field and angle.

Parameters
[in]eelectric field
[in]bmagnetic field
[in]bthetaangle between electric and magnetic field
[in]ncollnumber of collisions (in multiples of 107) to be simulated
[in]verboseverbosity flag
[out]vx,vy,vzdrift velocity vector
[out]dl,dtdiffusion cofficients
[out]alphaTownsend cofficient
[out]etaattachment cofficient
[out]lorLorentz angle
[out]vxerr,vyerr,vzerrerrors on drift velocity
[out]dlerr,dterrerrors on diffusion coefficients
[out]alphaerr,etaerrerrors on Townsend/attachment coefficients
[out]lorerrerror on Lorentz angle
[out]alphatofeffective Townsend coefficient $(\alpha - \eta)$ calculated using time-of-flight method
[out]difftenscomponents of the diffusion tensor (zz, xx, yy, xz, yz, xy)

Definition at line 3372 of file MediumMagboltz.cc.

3378 {
3379 // Initialize the values.
3380 vx = vy = vz = 0.;
3381 dl = dt = 0.;
3382 alpha = eta = alphatof = 0.;
3383 lor = 0.;
3384 vxerr = vyerr = vzerr = 0.;
3385 dlerr = dterr = 0.;
3386 alphaerr = etaerr = 0.;
3387 lorerr = 0.;
3388
3389 // Set the input parameters in the Magboltz common blocks.
3391 Magboltz::inpt_.nAniso = 2;
3392 if (m_autoEnergyLimit) {
3393 Magboltz::inpt_.efinal = 0.;
3394 } else {
3395 Magboltz::inpt_.efinal = std::min(m_eMax, m_eHigh);
3396 }
3397 Magboltz::inpt_.tempc = m_temperature - ZeroCelsius;
3399 Magboltz::inpt_.ipen = 0;
3400 Magboltz::setp_.nmax = ncoll;
3401
3402 Magboltz::thrm_.ithrm = m_useGasMotion ? 1 : 0;
3403
3404 Magboltz::setp_.efield = emag;
3405 // Convert from Tesla to kGauss.
3406 Magboltz::bfld_.bmag = bmag * 10.;
3407 // Convert from radians to degree.
3408 Magboltz::bfld_.btheta = btheta * RadToDegree;
3409
3410 // Set the gas composition in Magboltz.
3411 for (unsigned int i = 0; i < m_nComponents; ++i) {
3412 const int ng = GetGasNumberMagboltz(m_gas[i]);
3413 if (ng <= 0) {
3414 std::cerr << m_className << "::RunMagboltz:\n Gas " << m_gas[i]
3415 << " does not have a gas number in Magboltz.\n";
3416 return;
3417 }
3418 Magboltz::gasn_.ngasn[i] = ng;
3419 Magboltz::ratio_.frac[i] = 100 * m_fraction[i];
3420 }
3421
3422 // Run Magboltz.
3424
3425 // Velocities. Convert to cm / ns.
3426 vx = Magboltz::vel_.wx * 1.e-9;
3427 vxerr = Magboltz::velerr_.dwx;
3428 vy = Magboltz::vel_.wy * 1.e-9;
3429 vyerr = Magboltz::velerr_.dwy;
3430 vz = Magboltz::vel_.wz * 1.e-9;
3431 vzerr = Magboltz::velerr_.dwz;
3432
3433 // Calculate the Lorentz angle.
3434 const double vt = sqrt(vx * vx + vy * vy);
3435 const double v2 = (vx * vx + vy * vy + vz * vz);
3436 lor = atan2(vt, vz);
3437 if (vt > 0. && v2 > 0. && fabs(lor) > 0.) {
3438 const double dvx = vx * vxerr;
3439 const double dvy = vy * vyerr;
3440 const double dvz = vz * vzerr;
3441 const double a = vz / vt;
3442 lorerr = sqrt(a * a * (vx * vx * dvx * dvx + vy * vy * dvy * dvy) +
3443 vt * vt * dvz * dvz) /
3444 v2;
3445 lorerr /= lor;
3446 }
3447
3448 // Diffusion coefficients.
3449 dt = sqrt(0.2 * 0.5 * (Magboltz::diflab_.difxx + Magboltz::diflab_.difyy) /
3450 vz) *
3451 1.e-4;
3452 dterr = 0.5 * sqrt(Magboltz::diferl_.dfter * Magboltz::diferl_.dfter +
3453 vzerr * vzerr);
3454 dl = sqrt(0.2 * Magboltz::diflab_.difzz / vz) * 1.e-4;
3455 dlerr = 0.5 * sqrt(Magboltz::diferl_.dfler * Magboltz::diferl_.dfler +
3456 vzerr * vzerr);
3457 // Diffusion tensor.
3458 difftens[0] = 0.2e-4 * Magboltz::diflab_.difzz / vz;
3459 difftens[1] = 0.2e-4 * Magboltz::diflab_.difxx / vz;
3460 difftens[2] = 0.2e-4 * Magboltz::diflab_.difyy / vz;
3461 difftens[3] = 0.2e-4 * Magboltz::diflab_.difxz / vz;
3462 difftens[4] = 0.2e-4 * Magboltz::diflab_.difyz / vz;
3463 difftens[5] = 0.2e-4 * Magboltz::diflab_.difxy / vz;
3464 // Townsend and attachment coefficients.
3465 alpha = Magboltz::ctowns_.alpha;
3466 alphaerr = Magboltz::ctwner_.alper;
3467 eta = Magboltz::ctowns_.att;
3468 etaerr = Magboltz::ctwner_.atter;
3469
3470 // Calculate effective Townsend SST coefficient from TOF results.
3471 if (fabs(Magboltz::tofout_.tofdl) > 0.) {
3472 const double wrzn = 1.e5 * Magboltz::tofout_.tofwr;
3473 const double fc1 = 0.5 * wrzn / Magboltz::tofout_.tofdl;
3474 const double fc2 = (Magboltz::tofout_.ralpha -
3475 Magboltz::tofout_.rattof) * 1.e12 /
3476 Magboltz::tofout_.tofdl;
3477 alphatof = fc1 - sqrt(fc1 * fc1 - fc2);
3478 }
3479 // Print the results.
3480 if (!(m_debug || verbose)) return;
3481 std::cout << m_className << "::RunMagboltz: Results:\n";
3482 printf(" Drift velocity along E: %12.8f cm/ns +/- %5.2f%%\n", vz, vzerr);
3483 printf(" Drift velocity along Bt: %12.8f cm/ns +/- %5.2f%%\n", vx, vxerr);
3484 printf(" Drift velocity along ExB: %12.8f cm/ns +/- %5.2f%%\n", vy, vyerr);
3485 printf(" Lorentz angle: %12.3f degree\n", lor * RadToDegree);
3486 printf(" Longitudinal diffusion: %12.8f cm1/2 +/- %5.2f%%\n", dl, dlerr);
3487 printf(" Transverse diffusion: %12.8f cm1/2 +/- %5.2f%%\n", dt, dterr);
3488 printf(" Townsend coefficient: %12.4f cm-1 +/- %5.2f%%\n", alpha,
3489 alphaerr);
3490 printf(" Attachment coefficient: %12.4f cm-1 +/- %5.2f%%\n", eta,
3491 etaerr);
3492 if (alphatof > 0.) {
3493 printf(" TOF effective Townsend: %12.4f cm-1 (alpha - eta)\n",
3494 alphatof);
3495 }
3496}
std::array< double, m_nMaxGases > m_fraction
Definition: MediumGas.hh:130
struct Garfield::Magboltz::@17 diflab_
struct Garfield::Magboltz::@23 tofout_
struct Garfield::Magboltz::@16 velerr_
struct Garfield::Magboltz::@15 vel_
struct Garfield::Magboltz::@22 ctwner_
struct Garfield::Magboltz::@0 bfld_
struct Garfield::Magboltz::@14 ratio_
struct Garfield::Magboltz::@21 ctowns_
struct Garfield::Magboltz::@2 setp_
struct Garfield::Magboltz::@20 diferl_
struct Garfield::Magboltz::@3 thrm_
struct Garfield::Magboltz::@13 gasn_

Referenced by GenerateGasTable().

◆ SetExcitationScaling()

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

Multiply all excitation cross-sections by a uniform scaling factor.

Definition at line 335 of file MediumMagboltz.cc.

335 {
336 if (r <= 0.) {
337 std::cerr << m_className << "::SetExcitationScaling: Incorrect value.\n";
338 return;
339 }
340
341 // Get the "standard" name of this gas.
342 gasname = GetGasName(gasname);
343 if (gasname.empty()) {
344 std::cerr << m_className << "::SetExcitationScaling: Unknown gas name.\n";
345 return;
346 }
347
348 // Look for this gas in the present gas mixture.
349 bool found = false;
350 for (unsigned int i = 0; i < m_nComponents; ++i) {
351 if (m_gas[i] == gasname) {
352 m_scaleExc[i] = r;
353 found = true;
354 break;
355 }
356 }
357
358 if (!found) {
359 std::cerr << m_className << "::SetExcitationScaling:\n"
360 << " Specified gas (" << gasname
361 << ") is not part of the present gas mixture.\n";
362 return;
363 }
364
365 // Make sure that the collision rate table is updated.
366 m_isChanged = true;
367}

◆ SetMaxElectronEnergy()

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

Set the highest electron energy to be included in the table of scattering rates.

Definition at line 97 of file MediumMagboltz.cc.

97 {
98 if (e <= Small) {
99 std::cerr << m_className << "::SetMaxElectronEnergy: Invalid energy.\n";
100 return false;
101 }
102 m_eMax = e;
103
104 std::lock_guard<std::mutex> guard(m_mutex);
105 // Determine the energy interval size.
106 m_eStep = std::min(m_eMax, m_eHigh) / Magboltz::nEnergySteps;
107
108 // Force recalculation of the scattering rates table.
109 m_isChanged = true;
110
111 return true;
112}

Referenced by GetElectronCollision(), and GetElectronCollisionRate().

◆ SetMaxPhotonEnergy()

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

Set the highest photon energy to be included in the table of scattering rates.

Definition at line 114 of file MediumMagboltz.cc.

114 {
115 if (e <= Small) {
116 std::cerr << m_className << "::SetMaxPhotonEnergy: Invalid energy.\n";
117 return false;
118 }
119 m_eFinalGamma = e;
120
121 // Determine the energy interval size.
122 m_eStepGamma = m_eFinalGamma / nEnergyStepsGamma;
123
124 // Force recalculation of the scattering rates table.
125 m_isChanged = true;
126
127 return true;
128}

Referenced by GetPhotonCollision(), and GetPhotonCollisionRate().

◆ SetSplittingFunctionFlat()

void Garfield::MediumMagboltz::SetSplittingFunctionFlat ( )

Sample the secondary electron energy from a flat distribution.

Definition at line 153 of file MediumMagboltz.cc.

153 {
154 m_useOpalBeaty = false;
155 m_useGreenSawada = false;
156}

◆ SetSplittingFunctionGreenSawada()

void Garfield::MediumMagboltz::SetSplittingFunctionGreenSawada ( )

Sample the secondary electron energy according to the Green-Sawada model.

Definition at line 135 of file MediumMagboltz.cc.

135 {
136 m_useOpalBeaty = false;
137 m_useGreenSawada = true;
138 if (m_isChanged) return;
139
140 bool allset = true;
141 for (unsigned int i = 0; i < m_nComponents; ++i) {
142 if (!m_hasGreenSawada[i]) {
143 if (allset) {
144 std::cout << m_className << "::SetSplittingFunctionGreenSawada:\n";
145 allset = false;
146 }
147 std::cout << " Fit parameters for " << m_gas[i] << " not available.\n"
148 << " Using Opal-Beaty formula instead.\n";
149 }
150 }
151}

◆ SetSplittingFunctionOpalBeaty()

void Garfield::MediumMagboltz::SetSplittingFunctionOpalBeaty ( )

Sample the secondary electron energy according to the Opal-Beaty model.

Definition at line 130 of file MediumMagboltz.cc.

130 {
131 m_useOpalBeaty = true;
132 m_useGreenSawada = false;
133}

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