Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Garfield::ComponentTcadBase< N > Class Template Referenceabstract

Interpolation in a field map created by Sentaurus Device. More...

#include <ComponentTcadBase.hh>

+ Inheritance diagram for Garfield::ComponentTcadBase< N >:

Classes

struct  Defect
 
struct  Element
 
struct  Region
 

Public Member Functions

 ComponentTcadBase ()=delete
 Default constructor.
 
 ComponentTcadBase (const std::string &name)
 Constructor.
 
virtual ~ComponentTcadBase ()
 Destructor.
 
bool Initialise (const std::string &gridfilename, const std::string &datafilename)
 
bool SetWeightingField (const std::string &datfile1, const std::string &datfile2, const double dv, const std::string &label)
 
bool SetWeightingFieldShift (const std::string &label, const double x, const double y, const double z)
 
bool SetWeightingPotential (const std::string &datfile1, const std::string &datfile2, const double dv, const double t, const std::string &label)
 Import time-dependent weighting potentials at t > 0.
 
bool SetWeightingField (const std::string &datfile1, const std::string &datfile2, const double dv, const double t, const std::string &label)
 Import time-dependent weighting fields at t > 0.
 
void PrintRegions () const
 List all currently defined regions.
 
size_t GetNumberOfRegions () const
 Get the number of regions in the device.
 
void GetRegion (const size_t ireg, std::string &name, bool &active) const
 Get the name and "active volume" flag of a region.
 
void SetDriftRegion (const size_t ireg)
 Make a region active ("driftable").
 
void UnsetDriftRegion (const size_t ireg)
 Make a region inactive.
 
void SetMedium (const size_t ireg, Medium *m)
 Set the medium to be associated to a given region.
 
void SetMedium (const std::string &material, Medium *m)
 Set the medium to be associated to all regions with a given material.
 
size_t GetNumberOfElements () const
 Get the number of elements in the mesh.
 
size_t GetNumberOfNodes () const
 Get the number of vertices in the mesh.
 
void EnableVelocityMap (const bool on)
 Switch use of the imported velocity map on/off.
 
size_t GetNumberOfDonors ()
 Get the number of donor states found in the map.
 
size_t GetNumberOfAcceptors ()
 Get the number of acceptor states found in the map.
 
bool SetDonor (const size_t donorNumber, const double exsec, const double hxsec, const double concentration)
 
bool SetAcceptor (const size_t acceptorNumber, const double exsec, const double hxsec, const double concentration)
 Set the properties of an acceptor-type defect state.
 
void EnableAlphaMap (const bool on)
 Switch use of the imported impact ionisation map on/off.
 
void EnableAttachmentMap (const bool on)
 Switch use of the imported trapping map on/off.
 
bool GetElectronMobility (const double x, const double y, const double z, double &mob)
 Get the electron mobility at a given point in the mesh.
 
bool GetHoleMobility (const double x, const double y, const double z, double &mob)
 Get the hole mobility at a given point in the mesh.
 
void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label) override
 
double WeightingPotential (const double x, const double y, const double z, const std::string &label) override
 
void DelayedWeightingField (const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, const std::string &label) override
 
double DelayedWeightingPotential (const double x, const double y, const double z, const double t, const std::string &label) override
 
bool GetVoltageRange (double &vmin, double &vmax) override
 Calculate the voltage range [V].
 
bool HasVelocityMap () const override
 Does the component have velocity maps?
 
bool ElectronVelocity (const double x, const double y, const double z, double &vx, double &vy, double &vz) override
 Get the electron drift velocity.
 
bool HoleVelocity (const double x, const double y, const double z, double &vx, double &vy, double &vz) override
 Get the hole drift velocity.
 
bool HasTownsendMap () const override
 Does the component have maps of the Townsend coefficient?
 
bool HasAttachmentMap () const override
 Does the component have attachment maps?
 
bool ElectronAttachment (const double x, const double y, const double z, double &eta) override
 Get the electron attachment coefficient.
 
bool HoleAttachment (const double x, const double y, const double z, double &eta) override
 Get the hole attachment coefficient.
 
bool GetElectronLifetime (const double x, const double y, const double z, double &etau) override
 
bool GetHoleLifetime (const double x, const double y, const double z, double &htau) override
 
bool ElectronTownsend (const double x, const double y, const double z, double &alpha) override
 Get the electron Townsend coefficient.
 
bool HoleTownsend (const double x, const double y, const double z, double &alpha) override
 Get the hole Townsend coefficient.
 
- Public Member Functions inherited from Garfield::Component
 Component ()=delete
 Default constructor.
 
 Component (const std::string &name)
 Constructor.
 
virtual ~Component ()
 Destructor.
 
virtual void SetGeometry (Geometry *geo)
 Define the geometry.
 
virtual void Clear ()
 Reset.
 
virtual MediumGetMedium (const double x, const double y, const double z)
 Get the medium at a given location (x, y, z).
 
virtual void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)=0
 
virtual void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)=0
 Calculate the drift field [V/cm] and potential [V] at (x, y, z).
 
std::array< double, 3 > ElectricField (const double x, const double y, const double z)
 Calculate the drift field [V/cm] at (x, y, z).
 
virtual double ElectricPotential (const double x, const double y, const double z)
 Calculate the (drift) electrostatic potential [V] at (x, y, z).
 
virtual void MagneticField (const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
 
void SetMagneticField (const double bx, const double by, const double bz)
 Set a constant magnetic field.
 
virtual bool IsReady ()
 Ready for use?
 
virtual bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 Get the bounding box coordinates.
 
virtual bool GetElementaryCell (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 Get the coordinates of the elementary cell.
 
double IntegrateFluxCircle (const double xc, const double yc, const double r, const unsigned int nI=50)
 
double IntegrateFluxSphere (const double xc, const double yc, const double zc, const double r, const unsigned int nI=20)
 
double IntegrateFluxParallelogram (const double x0, const double y0, const double z0, const double dx1, const double dy1, const double dz1, const double dx2, const double dy2, const double dz2, const unsigned int nU=20, const unsigned int nV=20)
 
double IntegrateWeightingFluxParallelogram (const std::string &label, const double x0, const double y0, const double z0, const double dx1, const double dy1, const double dz1, const double dx2, const double dy2, const double dz2, const unsigned int nU=20, const unsigned int nV=20)
 
double IntegrateFluxLine (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, const double xp, const double yp, const double zp, const unsigned int nI, const int isign=0)
 
virtual bool CrossedWire (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc, const bool centre, double &rc)
 
virtual bool InTrapRadius (const double q0, const double x0, const double y0, const double z0, double &xw, double &yw, double &rw)
 
virtual bool CrossedPlane (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
 
void EnablePeriodicityX (const bool on=true)
 Enable simple periodicity in the $x$ direction.
 
void EnablePeriodicityY (const bool on=true)
 Enable simple periodicity in the $y$ direction.
 
void EnablePeriodicityZ (const bool on=true)
 Enable simple periodicity in the $z$ direction.
 
void IsPeriodic (bool &perx, bool &pery, bool &perz)
 Return periodicity flags.
 
void EnableMirrorPeriodicityX (const bool on=true)
 Enable mirror periodicity in the $x$ direction.
 
void EnableMirrorPeriodicityY (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void EnableMirrorPeriodicityZ (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void IsMirrorPeriodic (bool &perx, bool &pery, bool &perz)
 Return mirror periodicity flags.
 
void EnableAxialPeriodicityX (const bool on=true)
 Enable axial periodicity in the $x$ direction.
 
void EnableAxialPeriodicityY (const bool on=true)
 Enable axial periodicity in the $y$ direction.
 
void EnableAxialPeriodicityZ (const bool on=true)
 Enable axial periodicity in the $z$ direction.
 
void IsAxiallyPeriodic (bool &perx, bool &pery, bool &perz)
 Return axial periodicity flags.
 
void EnableRotationSymmetryX (const bool on=true)
 Enable rotation symmetry around the $x$ axis.
 
void EnableRotationSymmetryY (const bool on=true)
 Enable rotation symmetry around the $y$ axis.
 
void EnableRotationSymmetryZ (const bool on=true)
 Enable rotation symmetry around the $z$ axis.
 
void IsRotationSymmetric (bool &rotx, bool &roty, bool &rotz)
 Return rotation symmetry flags.
 
void EnableDebugging ()
 Switch on debugging messages.
 
void DisableDebugging ()
 Switch off debugging messages.
 
virtual bool HasMagneticField () const
 Does the component have a non-zero magnetic field?
 
virtual double StepSizeHint ()
 

Protected Member Functions

void UpdatePeriodicity () override
 Verify periodicities.
 
void Cleanup ()
 
virtual bool Interpolate (const double x, const double y, const double z, const std::vector< double > &field, double &f)=0
 
virtual bool Interpolate (const double x, const double y, const double z, const std::vector< std::array< double, N > > &field, double &fx, double &fy, double &fz)=0
 
virtual void FillTree ()=0
 
size_t FindRegion (const std::string &name) const
 
void MapCoordinates (std::array< double, N > &x, std::array< bool, N > &mirr) const
 
bool InBoundingBox (const std::array< double, N > &x) const
 
void UpdateAttachment ()
 
bool LoadGrid (const std::string &gridfilename)
 
bool LoadData (const std::string &datafilename)
 
bool ReadDataset (std::ifstream &datafile, const std::string &dataset)
 
bool LoadWeightingField (const std::string &datafilename, std::vector< std::array< double, N > > &wf, std::vector< double > &wp)
 
bool GetOffset (const std::string &label, double &dx, double &dy, double &dz) const
 
- Protected Member Functions inherited from Garfield::Component
virtual void Reset ()=0
 Reset the component.
 

Static Protected Member Functions

static unsigned int ElementVertices (const Element &element)
 

Protected Attributes

std::vector< Regionm_regions
 
std::vector< std::array< double, N > > m_vertices
 
std::vector< Elementm_elements
 
std::vector< double > m_epot
 
std::vector< std::array< double, N > > m_efield
 
std::vector< std::array< double, N > > m_wfield
 
std::vector< double > m_wpot
 
std::vector< std::string > m_wlabel
 
std::vector< std::array< double, 3 > > m_wshift
 
std::vector< std::vector< std::array< double, N > > > m_dwf
 
std::vector< std::vector< double > > m_dwp
 
std::vector< double > m_dwtf
 
std::vector< double > m_dwtp
 
std::vector< std::array< double, N > > m_eVelocity
 
std::vector< std::array< double, N > > m_hVelocity
 
std::vector< double > m_eMobility
 
std::vector< double > m_hMobility
 
std::vector< double > m_eAlpha
 
std::vector< double > m_hAlpha
 
std::vector< double > m_eLifetime
 
std::vector< double > m_hLifetime
 
std::vector< std::vector< float > > m_donorOcc
 
std::vector< std::vector< float > > m_acceptorOcc
 
std::vector< double > m_eAttachment
 
std::vector< double > m_hAttachment
 
std::vector< Defectm_donors
 
std::vector< Defectm_acceptors
 
bool m_useVelocityMap = false
 
bool m_useAttachmentMap = false
 
bool m_useAlphaMap = false
 
std::array< double, 3 > m_bbMin = {{0., 0., 0.}}
 
std::array< double, 3 > m_bbMax = {{0., 0., 0.}}
 
double m_pMin = 0.
 
double m_pMax = 0.
 
- Protected Attributes inherited from Garfield::Component
std::string m_className = "Component"
 Class name.
 
Geometrym_geometry = nullptr
 Pointer to the geometry.
 
std::array< double, 3 > m_b0 = {{0., 0., 0.}}
 Constant magnetic field.
 
bool m_ready = false
 Ready for use?
 
bool m_debug = false
 Switch on/off debugging messages.
 
std::array< bool, 3 > m_periodic = {{false, false, false}}
 Simple periodicity in x, y, z.
 
std::array< bool, 3 > m_mirrorPeriodic = {{false, false, false}}
 Mirror periodicity in x, y, z.
 
std::array< bool, 3 > m_axiallyPeriodic = {{false, false, false}}
 Axial periodicity in x, y, z.
 
std::array< bool, 3 > m_rotationSymmetric = {{false, false, false}}
 Rotation symmetry around x-axis, y-axis, z-axis.
 

Static Protected Attributes

static constexpr size_t nMaxVertices = 4
 

Detailed Description

template<size_t N>
class Garfield::ComponentTcadBase< N >

Interpolation in a field map created by Sentaurus Device.

Definition at line 14 of file ComponentTcadBase.hh.

Constructor & Destructor Documentation

◆ ComponentTcadBase() [1/2]

template<size_t N>
Garfield::ComponentTcadBase< N >::ComponentTcadBase ( )
delete

Default constructor.

◆ ComponentTcadBase() [2/2]

template<size_t N>
Garfield::ComponentTcadBase< N >::ComponentTcadBase ( const std::string & name)
inline

Constructor.

Definition at line 19 of file ComponentTcadBase.hh.

19 : Component(name) {
20 m_regions.reserve(10);
21 m_vertices.reserve(10000);
22 m_elements.reserve(10000);
23 }
Interpolation in a field map created by Sentaurus Device.
std::vector< std::array< double, N > > m_vertices
std::vector< Element > m_elements
std::vector< Region > m_regions
Component()=delete
Default constructor.

◆ ~ComponentTcadBase()

template<size_t N>
virtual Garfield::ComponentTcadBase< N >::~ComponentTcadBase ( )
inlinevirtual

Destructor.

Definition at line 25 of file ComponentTcadBase.hh.

25{}

Member Function Documentation

◆ Cleanup()

template<size_t N>
void Garfield::ComponentTcadBase< N >::Cleanup ( )
protected

Definition at line 1854 of file ComponentTcadBase.cc.

1854 {
1855 // Vertices
1856 m_vertices.clear();
1857 // Elements
1858 m_elements.clear();
1859 // Regions
1860 m_regions.clear();
1861 // Potential and electric field.
1862 m_epot.clear();
1863 m_efield.clear();
1864 // Weighting potential and field.
1865 m_wpot.clear();
1866 m_wfield.clear();
1867 m_wlabel.clear();
1868 m_wshift.clear();
1869 m_dwf.clear();
1870 m_dwp.clear();
1871 m_dwtp.clear();
1872 m_dwtf.clear();
1873
1874 // Other data.
1875 m_eVelocity.clear();
1876 m_hVelocity.clear();
1877 m_eMobility.clear();
1878 m_hMobility.clear();
1879 m_eAlpha.clear();
1880 m_hAlpha.clear();
1881 m_eLifetime.clear();
1882 m_hLifetime.clear();
1883 m_donors.clear();
1884 m_acceptors.clear();
1885 m_donorOcc.clear();
1886 m_acceptorOcc.clear();
1887 m_eAttachment.clear();
1888 m_hAttachment.clear();
1889}
std::vector< double > m_hMobility
std::vector< Defect > m_acceptors
std::vector< std::vector< float > > m_acceptorOcc
std::vector< std::string > m_wlabel
std::vector< std::array< double, 3 > > m_wshift
std::vector< std::vector< float > > m_donorOcc
std::vector< std::vector< double > > m_dwp
std::vector< double > m_eAttachment
std::vector< double > m_hAlpha
std::vector< double > m_eAlpha
std::vector< std::array< double, N > > m_hVelocity
std::vector< std::array< double, N > > m_efield
std::vector< std::array< double, N > > m_eVelocity
std::vector< double > m_hLifetime
std::vector< std::vector< std::array< double, N > > > m_dwf
std::vector< Defect > m_donors
std::vector< double > m_eMobility
std::vector< std::array< double, N > > m_wfield
std::vector< double > m_hAttachment
std::vector< double > m_eLifetime

Referenced by Initialise(), and LoadGrid().

◆ DelayedWeightingField()

template<size_t N>
void Garfield::ComponentTcadBase< N >::DelayedWeightingField ( const double x,
const double y,
const double z,
const double t,
double & wx,
double & wy,
double & wz,
const std::string & label )
overridevirtual

Calculate the delayed weighting field at a given point and time and for a given electrode.

Parameters
x,y,zcoordinates [cm].
ttime [ns].
wx,wy,wzcomponents of the weighting field [1/cm].
labelname of the electrode

Reimplemented from Garfield::Component.

Definition at line 79 of file ComponentTcadBase.cc.

81 {
82 wx = wy = wz = 0.;
83 if (m_dwf.empty()) {
84 std::cerr << m_className << "::DelayedWeightingField: Not available.\n";
85 return;
86 }
87 if (m_dwtf.empty()) return;
88 if (t < m_dwtf.front() || t > m_dwtf.back()) return;
89
90 double dx = 0., dy = 0., dz = 0.;
91 if (!GetOffset(label, dx, dy, dz)) return;
92
93 const auto it1 = std::upper_bound(m_dwtf.cbegin(), m_dwtf.cend(), t);
94 const auto it0 = std::prev(it1);
95 const double dt = t - *it0;
96 const auto i0 = std::distance(m_dwtf.cbegin(), it0);
97 double wx0 = 0., wy0 = 0., wz0 = 0.;
98 Interpolate(x - dx, y - dy, z - dz, m_dwf[i0], wx0, wy0, wz0);
99 if (dt < Small || it1 == m_dwtf.cend()) {
100 wx = wx0;
101 wy = wy0;
102 wz = wz0;
103 return;
104 }
105 const auto i1 = std::distance(m_dwtf.cbegin(), it1);
106 double wx1 = 0., wy1 = 0., wz1 = 0.;
107 Interpolate(x - dx, y - dy, z - dz, m_dwf[i1], wx1, wy1, wz1);
108 const double f1 = dt / (*it1 - *it0);
109 const double f0 = 1. - f1;
110 wx = f0 * wx0 + f1 * wx1;
111 wy = f0 * wy0 + f1 * wy1;
112 wz = f0 * wz0 + f1 * wz1;
113}
virtual bool Interpolate(const double x, const double y, const double z, const std::vector< double > &field, double &f)=0
bool GetOffset(const std::string &label, double &dx, double &dy, double &dz) const
std::string m_className
Class name.
Definition Component.hh:359

◆ DelayedWeightingPotential()

template<size_t N>
double Garfield::ComponentTcadBase< N >::DelayedWeightingPotential ( const double x,
const double y,
const double z,
const double t,
const std::string & label )
overridevirtual

Calculate the delayed weighting potential at a given point and time and for a given electrode.

Parameters
x,y,zcoordinates [cm].
ttime [ns].
labelname of the electrode

Reimplemented from Garfield::Component.

Definition at line 116 of file ComponentTcadBase.cc.

118 {
119
120 if (m_dwp.empty()) {
121 std::cerr << m_className << "::DelayedWeightingPotential: Not available.\n";
122 return 0.;
123 }
124 if (m_dwtp.empty()) return 0.;
125 if (t < m_dwtp.front() || t > m_dwtp.back()) return 0.;
126
127 double dx = 0., dy = 0., dz = 0.;
128 if (!GetOffset(label, dx, dy, dz)) return 0.;
129
130 const auto it1 = std::upper_bound(m_dwtp.cbegin(), m_dwtp.cend(), t);
131 const auto it0 = std::prev(it1);
132 const double dt = t - *it0;
133 const auto i0 = std::distance(m_dwtp.cbegin(), it0);
134 double v0 = 0.;
135 Interpolate(x - dx, y - dy, z - dz, m_dwp[i0], v0);
136 if (dt < Small || it1 == m_dwtp.cend()) return v0;
137
138 const auto i1 = std::distance(m_dwtp.cbegin(), it1);
139 double v1 = 0.;
140 Interpolate(x - dx, y - dy, z - dz, m_dwp[i1], v1);
141 const double f1 = dt / (*it1 - *it0);
142 const double f0 = 1. - f1;
143 return f0 * v0 + f1 * v1;
144}

◆ ElectronAttachment()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::ElectronAttachment ( const double ,
const double ,
const double ,
double & eta )
overridevirtual

Get the electron attachment coefficient.

Reimplemented from Garfield::Component.

Definition at line 1760 of file ComponentTcadBase.cc.

1761 {
1763 return true;
1764}

◆ ElectronTownsend()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::ElectronTownsend ( const double ,
const double ,
const double ,
double & alpha )
overridevirtual

Get the electron Townsend coefficient.

Reimplemented from Garfield::Component.

Definition at line 1774 of file ComponentTcadBase.cc.

1775 {
1777 return true;
1778}

◆ ElectronVelocity()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::ElectronVelocity ( const double ,
const double ,
const double ,
double & vx,
double & vy,
double & vz )
overridevirtual

Get the electron drift velocity.

Reimplemented from Garfield::Component.

Definition at line 1788 of file ComponentTcadBase.cc.

1790 {
1791 return Interpolate(x, y, z, m_eVelocity, vx, vy, vz);
1792}

◆ ElementVertices()

template<size_t N>
static unsigned int Garfield::ComponentTcadBase< N >::ElementVertices ( const Element & element)
inlinestaticprotected

Definition at line 273 of file ComponentTcadBase.hh.

273 {
274 return std::min(element.type + 1, 4U);
275 }

Referenced by Initialise(), LoadWeightingField(), and ReadDataset().

◆ EnableAlphaMap()

template<size_t N>
void Garfield::ComponentTcadBase< N >::EnableAlphaMap ( const bool on)
inline

Switch use of the imported impact ionisation map on/off.

Definition at line 102 of file ComponentTcadBase.hh.

◆ EnableAttachmentMap()

template<size_t N>
void Garfield::ComponentTcadBase< N >::EnableAttachmentMap ( const bool on)
inline

Switch use of the imported trapping map on/off.

Definition at line 105 of file ComponentTcadBase.hh.

◆ EnableVelocityMap()

template<size_t N>
void Garfield::ComponentTcadBase< N >::EnableVelocityMap ( const bool on)

Switch use of the imported velocity map on/off.

Definition at line 598 of file ComponentTcadBase.cc.

598 {
600 if (m_ready && (m_eVelocity.empty() && m_hVelocity.empty())) {
601 std::cout << m_className << "::EnableVelocityMap:\n"
602 << " Warning: current map does not include velocity data.\n";
603 }
604}
bool m_ready
Ready for use?
Definition Component.hh:368

◆ FillTree()

template<size_t N>
virtual void Garfield::ComponentTcadBase< N >::FillTree ( )
protectedpure virtual

◆ FindRegion()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::FindRegion ( const std::string & name) const
protected

Definition at line 1915 of file ComponentTcadBase.cc.

1915 {
1916 const auto nRegions = m_regions.size();
1917 for (size_t j = 0; j < nRegions; ++j) {
1918 if (name == m_regions[j].name) return j;
1919 }
1920 return m_regions.size();
1921}

Referenced by LoadGrid(), LoadWeightingField(), and ReadDataset().

◆ GetElectronLifetime()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetElectronLifetime ( const double x,
const double y,
const double z,
double & etau )
overridevirtual

Reimplemented from Garfield::Component.

Definition at line 1802 of file ComponentTcadBase.cc.

1803 {
1804 return Interpolate(x, y, z, m_eLifetime, tau);
1805}

◆ GetElectronMobility()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetElectronMobility ( const double x,
const double y,
const double z,
double & mob )

Get the electron mobility at a given point in the mesh.

Definition at line 1814 of file ComponentTcadBase.cc.

1815 {
1816 return Interpolate(x, y, z, m_eMobility, mob);
1817}

◆ GetHoleLifetime()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetHoleLifetime ( const double x,
const double y,
const double z,
double & htau )
overridevirtual

Reimplemented from Garfield::Component.

Definition at line 1808 of file ComponentTcadBase.cc.

1809 {
1810 return Interpolate(x, y, z, m_hLifetime, tau);
1811}

◆ GetHoleMobility()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetHoleMobility ( const double x,
const double y,
const double z,
double & mob )

Get the hole mobility at a given point in the mesh.

Definition at line 1820 of file ComponentTcadBase.cc.

1821 {
1822 return Interpolate(x, y, z, m_hMobility, mob);
1823}

◆ GetNumberOfAcceptors()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::GetNumberOfAcceptors ( )
inline

Get the number of acceptor states found in the map.

Definition at line 87 of file ComponentTcadBase.hh.

87{ return m_acceptors.size(); }

◆ GetNumberOfDonors()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::GetNumberOfDonors ( )
inline

Get the number of donor states found in the map.

Definition at line 85 of file ComponentTcadBase.hh.

85{ return m_donors.size(); }

◆ GetNumberOfElements()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::GetNumberOfElements ( ) const
inline

Get the number of elements in the mesh.

Definition at line 77 of file ComponentTcadBase.hh.

77{ return m_elements.size(); }

◆ GetNumberOfNodes()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::GetNumberOfNodes ( ) const
inline

Get the number of vertices in the mesh.

Definition at line 79 of file ComponentTcadBase.hh.

79{ return m_vertices.size(); }

◆ GetNumberOfRegions()

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::GetNumberOfRegions ( ) const
inline

Get the number of regions in the device.

Definition at line 64 of file ComponentTcadBase.hh.

64{ return m_regions.size(); }

Referenced by main().

◆ GetOffset()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetOffset ( const std::string & label,
double & dx,
double & dy,
double & dz ) const
protected

Definition at line 147 of file ComponentTcadBase.cc.

148 {
149
150 const auto it = std::find(m_wlabel.cbegin(), m_wlabel.cend(), label);
151 if (it == m_wlabel.end()) return false;
152 const auto i = std::distance(m_wlabel.begin(), it);
153 dx = m_wshift[i][0];
154 dy = m_wshift[i][1];
155 dz = m_wshift[i][2];
156 return true;
157}

◆ GetRegion()

template<size_t N>
void Garfield::ComponentTcadBase< N >::GetRegion ( const size_t ireg,
std::string & name,
bool & active ) const

Get the name and "active volume" flag of a region.

Definition at line 1663 of file ComponentTcadBase.cc.

1664 {
1665 if (i >= m_regions.size()) {
1666 std::cerr << m_className << "::GetRegion: Index out of range.\n";
1667 return;
1668 }
1669 name = m_regions[i].name;
1670 active = m_regions[i].drift;
1671}

◆ GetVoltageRange()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::GetVoltageRange ( double & vmin,
double & vmax )
overridevirtual

Calculate the voltage range [V].

Implements Garfield::Component.

Definition at line 342 of file ComponentTcadBase.cc.

342 {
343 if (!m_ready) return false;
344 vmin = m_pMin;
345 vmax = m_pMax;
346 return true;
347}

◆ HasAttachmentMap()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HasAttachmentMap ( ) const
inlineoverridevirtual

Does the component have attachment maps?

Reimplemented from Garfield::Component.

Definition at line 140 of file ComponentTcadBase.hh.

140 {
141 return (m_useAttachmentMap && !(m_acceptors.empty() && m_donors.empty()));
142 }

◆ HasTownsendMap()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HasTownsendMap ( ) const
inlineoverridevirtual

Does the component have maps of the Townsend coefficient?

Reimplemented from Garfield::Component.

Definition at line 137 of file ComponentTcadBase.hh.

137 {
138 return m_useAlphaMap && !(m_eAlpha.empty() && m_hAlpha.empty());
139 }

◆ HasVelocityMap()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HasVelocityMap ( ) const
inlineoverridevirtual

Does the component have velocity maps?

Reimplemented from Garfield::Component.

Definition at line 129 of file ComponentTcadBase.hh.

129 {
130 return m_useVelocityMap && !(m_eVelocity.empty() && m_hVelocity.empty());
131 }

◆ HoleAttachment()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HoleAttachment ( const double ,
const double ,
const double ,
double & eta )
overridevirtual

Get the hole attachment coefficient.

Reimplemented from Garfield::Component.

Definition at line 1767 of file ComponentTcadBase.cc.

1768 {
1770 return true;
1771}

◆ HoleTownsend()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HoleTownsend ( const double ,
const double ,
const double ,
double & alpha )
overridevirtual

Get the hole Townsend coefficient.

Reimplemented from Garfield::Component.

Definition at line 1781 of file ComponentTcadBase.cc.

1782 {
1784 return true;
1785}

◆ HoleVelocity()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::HoleVelocity ( const double ,
const double ,
const double ,
double & vx,
double & vy,
double & vz )
overridevirtual

Get the hole drift velocity.

Reimplemented from Garfield::Component.

Definition at line 1795 of file ComponentTcadBase.cc.

1797 {
1798 return Interpolate(x, y, z, m_hVelocity, vx, vy, vz);
1799}

◆ InBoundingBox()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::InBoundingBox ( const std::array< double, N > & x) const
inlineprotected

Definition at line 286 of file ComponentTcadBase.hh.

286 {
287 for (size_t i = 0; i < N; ++i) {
288 if (x[i] < m_bbMin[i] || x[i] > m_bbMax[i]) return false;
289 }
290 return true;
291 }
std::array< double, 3 > m_bbMax
std::array< double, 3 > m_bbMin

◆ Initialise()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::Initialise ( const std::string & gridfilename,
const std::string & datafilename )

Import mesh and field map from files.

Parameters
gridfilenamename of the .grd file containing the mesh
datafilenamename of the .dat file containing the nodal solution

Definition at line 160 of file ComponentTcadBase.cc.

161 {
162
163 m_ready = false;
164 Cleanup();
165 // Import mesh data from .grd file.
166 if (!LoadGrid(gridfilename)) {
167 std::cerr << m_className << "::Initialise:\n"
168 << " Importing mesh data failed.\n";
169 Cleanup();
170 return false;
171 }
172 // Import electric field, potential and other data from .dat file.
173 if (!LoadData(datafilename)) {
174 std::cerr << m_className << "::Initialise:\n"
175 << " Importing electric field and potential failed.\n";
176 Cleanup();
177 return false;
178 }
179
180 // Find min./max. coordinates and potentials.
181 for (size_t i = 0; i < N; ++i) {
182 m_bbMax[i] = m_vertices[m_elements[0].vertex[0]][i];
183 m_bbMin[i] = m_bbMax[i];
184 }
185 const size_t nElements = m_elements.size();
186 for (size_t i = 0; i < nElements; ++i) {
190 const auto nV = ElementVertices(m_elements[i]);
191 for (unsigned int j = 0; j < nV; ++j) {
192 const auto& v = m_vertices[m_elements[i].vertex[j]];
193 for (size_t k = 0; k < N; ++k) {
194 xmin[k] = std::min(xmin[k], v[k]);
195 xmax[k] = std::max(xmax[k], v[k]);
196 }
197 }
198 constexpr double tol = 1.e-6;
199 for (size_t k = 0; k < N; ++k) {
200 m_elements[i].bbMin[k] = xmin[k] - tol;
201 m_elements[i].bbMax[k] = xmax[k] + tol;
204 }
205 }
206 m_pMin = *std::min_element(m_epot.begin(), m_epot.end());
207 m_pMax = *std::max_element(m_epot.begin(), m_epot.end());
208
209 std::cout << m_className << "::Initialise:\n"
210 << " Available data:\n";
211 if (!m_epot.empty()) std::cout << " Electrostatic potential\n";
212 if (!m_efield.empty()) std::cout << " Electric field\n";
213 if (!m_eMobility.empty()) std::cout << " Electron mobility\n";
214 if (!m_hMobility.empty()) std::cout << " Hole mobility\n";
215 if (!m_eVelocity.empty()) std::cout << " Electron velocity\n";
216 if (!m_hVelocity.empty()) std::cout << " Hole velocity\n";
217 if (!m_eAlpha.empty()) std::cout << " Electron impact ionisation\n";
218 if (!m_hAlpha.empty()) std::cout << " Hole impact ionisation\n";
219 if (!m_eLifetime.empty()) std::cout << " Electron lifetime\n";
220 if (!m_hLifetime.empty()) std::cout << " Hole lifetime\n";
221 if (!m_donors.empty()) {
222 std::cout << " " << m_donors.size() << " donor-type traps\n";
223 }
224 if (!m_acceptors.empty()) {
225 std::cout << " " << m_acceptors.size() << " acceptor-type traps\n";
226 }
227 const std::array<std::string, 3> axes = {"x", "y", "z"};
228 std::cout << " Bounding box:\n";
229 for (size_t i = 0; i < N; ++i) {
230 std::cout << " " << m_bbMin[i] << " < " << axes[i] << " [cm] < "
231 << m_bbMax[i] << "\n";
232 }
233 std::cout << " Voltage range:\n"
234 << " " << m_pMin << " < V < " << m_pMax << "\n";
235
236 bool ok = true;
237
238 // Count the number of elements belonging to a region.
239 const auto nRegions = m_regions.size();
241 // Keep track of elements that are not part of any region.
243
244 // Count the different element shapes.
246 if (N == 2) {
247 nElementsByShape = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
248 } else {
249 nElementsByShape = {{2, 0}, {5, 0}};
250 }
251 unsigned int nElementsOther = 0;
252
253 // Keep track of degenerate elements.
255
256 for (size_t i = 0; i < nElements; ++i) {
257 const Element& element = m_elements[i];
258 if (element.region < nRegions) {
259 ++nElementsByRegion[element.region];
260 } else {
261 looseElements.push_back(i);
262 }
263 if (nElementsByShape.count(element.type) == 0) {
265 continue;
266 }
267 nElementsByShape[element.type] += 1;
268 bool degenerate = false;
269 const auto nV = ElementVertices(m_elements[i]);
270 for (unsigned int j = 0; j < nV; ++j) {
271 for (unsigned int k = j + 1; k < nV; ++k) {
272 if (element.vertex[j] == element.vertex[k]) {
273 degenerate = true;
274 break;
275 }
276 }
277 if (degenerate) break;
278 }
279 if (degenerate) {
280 degenerateElements.push_back(i);
281 }
282 }
283
284 if (!degenerateElements.empty()) {
285 std::cerr << m_className << "::Initialise:\n"
286 << " The following elements are degenerate:\n";
287 for (size_t i : degenerateElements) std::cerr << " " << i << "\n";
288 ok = false;
289 }
290
291 if (!looseElements.empty()) {
292 std::cerr << m_className << "::Initialise:\n"
293 << " The following elements are not part of any region:\n";
294 for (size_t i : looseElements) std::cerr << " " << i << "\n";
295 ok = false;
296 }
297
298 std::cout << m_className << "::Initialise:\n"
299 << " Number of regions: " << nRegions << "\n";
300 for (size_t i = 0; i < nRegions; ++i) {
301 std::cout << " " << i << ": " << m_regions[i].name;
302 if (!m_regions[i].material.empty()) {
303 std::cout << " (" << m_regions[i].material << ")";
304 }
305 std::cout << ", " << nElementsByRegion[i] << " elements\n";
306 }
307
309 {0, "points"}, {1, "lines"}, {2, "triangles"}, {3, "rectangles"},
310 {5, "tetrahedra"}};
311
312 std::cout << " Number of elements: " << nElements << "\n";
313 for (const auto& n : nElementsByShape) {
314 if (n.second > 0) {
315 std::cout << " " << n.second << " " << shapes[n.first] << "\n";
316 }
317 }
318 if (nElementsOther > 0) {
319 std::cerr << " " << nElementsOther << " elements of unknown type.\n"
320 << " Program bug!\n";
321 m_ready = false;
322 Cleanup();
323 return false;
324 }
325
326 std::cout << " Number of vertices: " << m_vertices.size() << "\n";
327 if (!ok) {
328 m_ready = false;
329 Cleanup();
330 return false;
331 }
332
333 FillTree();
334
335 m_ready = true;
337 std::cout << m_className << "::Initialise: Initialisation finished.\n";
338 return true;
339}
bool LoadGrid(const std::string &gridfilename)
virtual void FillTree()=0
static unsigned int ElementVertices(const Element &element)
bool LoadData(const std::string &datafilename)
void UpdatePeriodicity() override
Verify periodicities.

Referenced by main().

◆ Interpolate() [1/2]

template<size_t N>
virtual bool Garfield::ComponentTcadBase< N >::Interpolate ( const double x,
const double y,
const double z,
const std::vector< double > & field,
double & f )
protectedpure virtual

◆ Interpolate() [2/2]

template<size_t N>
virtual bool Garfield::ComponentTcadBase< N >::Interpolate ( const double x,
const double y,
const double z,
const std::vector< std::array< double, N > > & field,
double & fx,
double & fy,
double & fz )
protectedpure virtual

◆ LoadData()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::LoadData ( const std::string & datafilename)
protected

Definition at line 1175 of file ComponentTcadBase.cc.

1175 {
1176
1178 if (!datafile) {
1179 std::cerr << m_className << "::LoadData:\n"
1180 << " Could not open file " << filename << ".\n";
1181 return false;
1182 }
1183 const size_t nVertices = m_vertices.size();
1185
1187 zeroes.fill(0.);
1188 // Read the file line by line.
1190 while (std::getline(datafile, line)) {
1191 // Strip white space from the beginning of the line.
1192 ltrim(line);
1193 // Skip empty lines.
1194 if (line.empty()) continue;
1195 // Find data section.
1196 if (line.substr(0, 8) != "function") continue;
1197 // Read type of data set.
1198 const auto pEq = line.find('=');
1199 if (pEq == std::string::npos) {
1200 // No "=" found.
1201 std::cerr << m_className << "::LoadData:\n"
1202 << " Error reading file " << filename << ".\n"
1203 << " Line:\n " << line << "\n";
1204 return false;
1205 }
1206 line = line.substr(pEq + 1);
1209 data >> dataset;
1210 data.clear();
1211 if (m_debug && dataset != "[") {
1212 std::cout << m_className << "::LoadData: Found dataset "
1213 << dataset << ".\n";
1214 }
1215 if (dataset == "ElectrostaticPotential") {
1216 if (m_epot.empty()) m_epot.assign(nVertices, 0.);
1217 if (!ReadDataset(datafile, dataset)) {
1218 m_epot.clear();
1219 return false;
1220 }
1221 } else if (dataset == "ElectricField") {
1222 if (m_efield.empty()) m_efield.assign(nVertices, zeroes);
1223 if (!ReadDataset(datafile, dataset)) {
1224 m_efield.clear();
1225 return false;
1226 }
1227 } else if (dataset == "eDriftVelocity") {
1228 if (m_eVelocity.empty()) m_eVelocity.assign(nVertices, zeroes);
1229 if (!ReadDataset(datafile, dataset)) {
1230 m_eVelocity.clear();
1231 return false;
1232 }
1233 } else if (dataset == "hDriftVelocity") {
1234 if (m_hVelocity.empty()) m_hVelocity.assign(nVertices, zeroes);
1235 if (!ReadDataset(datafile, dataset)) {
1236 m_hVelocity.clear();
1237 return false;
1238 }
1239 } else if (dataset == "eMobility") {
1240 if (m_eMobility.empty()) m_eMobility.assign(nVertices, 0.);
1241 if (!ReadDataset(datafile, dataset)) {
1242 m_eMobility.clear();
1243 return false;
1244 }
1245 } else if (dataset == "hMobility") {
1246 if (m_hMobility.empty()) m_hMobility.assign(nVertices, 0.);
1247 if (!ReadDataset(datafile, dataset)) {
1248 m_hMobility.clear();
1249 return false;
1250 }
1251 } else if (dataset == "eAlphaAvalanche") {
1252 if (m_eAlpha.empty()) m_eAlpha.assign(nVertices, 0.);
1253 if (!ReadDataset(datafile, dataset)) {
1254 m_eAlpha.clear();
1255 return false;
1256 }
1257 } else if (dataset == "hAlphaAvalanche") {
1258 if (m_hAlpha.empty()) m_hAlpha.assign(nVertices, 0.);
1259 if (!ReadDataset(datafile, dataset)) {
1260 m_hAlpha.clear();
1261 return false;
1262 }
1263 } else if (dataset == "eLifetime") {
1264 if (m_eLifetime.empty()) m_eLifetime.assign(nVertices, 0.);
1265 if (!ReadDataset(datafile, dataset)) {
1266 m_eLifetime.clear();
1267 return false;
1268 }
1269 } else if (dataset == "hLifetime") {
1270 if (m_hLifetime.empty()) m_hLifetime.assign(nVertices, 0.);
1271 if (!ReadDataset(datafile, dataset)) {
1272 m_hLifetime.clear();
1273 return false;
1274 }
1275 } else if (dataset.substr(0, 14) == "TrapOccupation" &&
1276 dataset.substr(17, 2) == "Do") {
1277 if (!ReadDataset(datafile, dataset)) return false;
1278 Defect donor;
1279 donor.xsece = -1.;
1280 donor.xsech = -1.;
1281 donor.conc = -1.;
1282 m_donors.push_back(donor);
1283 } else if (dataset.substr(0, 14) == "TrapOccupation" &&
1284 dataset.substr(17, 2) == "Ac") {
1285 if (!ReadDataset(datafile, dataset)) return false;
1287 acceptor.xsece = -1.;
1288 acceptor.xsech = -1.;
1289 acceptor.conc = -1.;
1290 m_acceptors.push_back(acceptor);
1291 }
1292 }
1293 if (datafile.fail() && !datafile.eof()) {
1294 std::cerr << m_className << "::LoadData:\n"
1295 << " Error reading file " << filename << "\n";
1296 return false;
1297 }
1298 return true;
1299}
bool ReadDataset(std::ifstream &datafile, const std::string &dataset)
bool m_debug
Switch on/off debugging messages.
Definition Component.hh:371
void ltrim(std::string &line)
Definition Utilities.hh:12

Referenced by Initialise().

◆ LoadGrid()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::LoadGrid ( const std::string & gridfilename)
protected

Definition at line 607 of file ComponentTcadBase.cc.

607 {
608 // Open the file containing the mesh description.
610 if (!gridfile) {
611 std::cerr << m_className << "::LoadGrid:\n"
612 << " Could not open file " << filename << ".\n";
613 return false;
614 }
615 // Delete existing mesh information.
616 Cleanup();
617 // Count line numbers.
618 unsigned int iLine = 0;
619 // Get the number of regions.
620 size_t nRegions = 0;
621 // Read the file line by line.
623 while (std::getline(gridfile, line)) {
624 ++iLine;
625 // Strip white space from the beginning of the line.
626 ltrim(line);
627 if (line.empty()) continue;
628 // Find entry 'nb_regions'.
629 if (line.substr(0, 10) != "nb_regions") continue;
630 const auto pEq = line.find('=');
631 if (pEq == std::string::npos) {
632 // No "=" sign found.
633 std::cerr << m_className << "::LoadGrid:\n"
634 << " Could not read number of regions.\n";
635 return false;
636 }
637 line = line.substr(pEq + 1);
639 data >> nRegions;
640 break;
641 }
642 if (gridfile.eof()) {
643 // Reached end of file.
644 std::cerr << m_className << "::LoadGrid:\n"
645 << " Could not find entry 'nb_regions' in file\n"
646 << " " << filename << ".\n";
647 return false;
648 } else if (gridfile.fail()) {
649 // Error reading from the file.
650 PrintError(m_className + "::LoadGrid", filename, iLine);
651 return false;
652 }
653 m_regions.resize(nRegions);
654 for (size_t j = 0; j < nRegions; ++j) {
655 m_regions[j].name = "";
656 m_regions[j].material = "";
657 m_regions[j].drift = false;
658 m_regions[j].medium = nullptr;
659 }
660 if (m_debug) {
661 std::cout << m_className << "::LoadGrid:\n"
662 << " Found " << nRegions << " regions.\n";
663 }
664 // Get the region names.
665 while (std::getline(gridfile, line)) {
666 ++iLine;
667 ltrim(line);
668 if (line.empty()) continue;
669 // Find entry 'regions'.
670 if (line.substr(0, 7) != "regions") continue;
671 // Get region names (given in brackets).
673 std::cerr << m_className << "::LoadGrid:\n"
674 << " Could not read region names.\n";
675 return false;
676 }
678 for (size_t j = 0; j < nRegions; ++j) {
679 data >> m_regions[j].name;
680 data.clear();
681 // Assume by default that all regions are active.
682 m_regions[j].drift = true;
683 m_regions[j].medium = nullptr;
684 }
685 break;
686 }
687 if (gridfile.eof()) {
688 // Reached end of file.
689 std::cerr << m_className << "::LoadGrid:\n"
690 << " Could not find entry 'regions' in file\n"
691 << " " << filename << ".\n";
692 return false;
693 } else if (gridfile.fail()) {
694 // Error reading from the file.
695 PrintError(m_className + "::LoadGrid", filename, iLine);
696 return false;
697 }
698
699 // Get the materials.
700 while (std::getline(gridfile, line)) {
701 ++iLine;
702 ltrim(line);
703 if (line.empty()) continue;
704 // Find entry 'materials'.
705 if (line.substr(0, 9) != "materials") continue;
706 // Get region names (given in brackets).
708 std::cerr << m_className << "::LoadGrid:\n"
709 << " Could not read materials.\n";
710 return false;
711 }
713 for (size_t j = 0; j < nRegions; ++j) {
714 data >> m_regions[j].material;
715 data.clear();
716 }
717 break;
718 }
719 if (gridfile.eof()) {
720 // Reached end of file.
721 std::cerr << m_className << "::LoadGrid:\n"
722 << " Could not find entry 'materials' in file\n"
723 << " " << filename << ".\n";
724 } else if (gridfile.fail()) {
725 // Error reading from the file.
726 PrintError(m_className + "::LoadGrid", filename, iLine);
727 }
728
729 // Get the vertices.
730 size_t nVertices = 0;
731 while (std::getline(gridfile, line)) {
732 ++iLine;
733 ltrim(line);
734 if (line.empty()) continue;
735 // Find section 'Vertices'.
736 if (line.substr(0, 8) != "Vertices") continue;
737 // Get number of vertices (given in brackets).
739 std::cerr << m_className << "::LoadGrid:\n"
740 << " Could not read number of vertices.\n";
741 return false;
742 }
744 data >> nVertices;
745 m_vertices.resize(nVertices);
746 // Get the coordinates of every vertex.
747 for (size_t j = 0; j < nVertices; ++j) {
748 for (size_t k = 0; k < N; ++k) {
749 gridfile >> m_vertices[j][k];
750 // Change units from micron to cm.
751 m_vertices[j][k] *= 1.e-4;
752 }
753 ++iLine;
754 }
755 break;
756 }
757 if (gridfile.eof()) {
758 std::cerr << m_className << "::LoadGrid:\n"
759 << " Could not find section 'Vertices' in file\n"
760 << " " << filename << ".\n";
761 return false;
762 } else if (gridfile.fail()) {
763 PrintError(m_className + "::LoadGrid", filename, iLine);
764 return false;
765 }
766
767 // Get the "edges" (lines connecting two vertices).
768 size_t nEdges = 0;
769 // Temporary arrays for storing edge points.
772 while (std::getline(gridfile, line)) {
773 ++iLine;
774 ltrim(line);
775 if (line.empty()) continue;
776 // Find section 'Edges'.
777 if (line.substr(0, 5) != "Edges") continue;
778 // Get the number of edges (given in brackets).
780 std::cerr << m_className << "::LoadGrid:\n"
781 << " Could not read number of edges.\n";
782 return false;
783 }
785 data >> nEdges;
786 edgeP1.resize(nEdges);
787 edgeP2.resize(nEdges);
788 // Get the indices of the two endpoints.
789 for (size_t j = 0; j < nEdges; ++j) {
790 gridfile >> edgeP1[j] >> edgeP2[j];
791 ++iLine;
792 }
793 break;
794 }
795 if (gridfile.eof()) {
796 std::cerr << m_className << "::LoadGrid:\n"
797 << " Could not find section 'Edges' in file\n"
798 << " " << filename << ".\n";
799 return false;
800 } else if (gridfile.fail()) {
801 PrintError(m_className + "::LoadGrid", filename, iLine);
802 return false;
803 }
804
805 for (size_t i = 0; i < nEdges; ++i) {
806 // Make sure the indices of the edge endpoints are not out of range.
807 if (edgeP1[i] >= nVertices || edgeP2[i] >= nVertices) {
808 std::cerr << m_className << "::LoadGrid:\n"
809 << " Vertex index of edge " << i << " out of range.\n";
810 return false;
811 }
812 // Make sure the edge is non-degenerate.
813 if (edgeP1[i] == edgeP2[i]) {
814 std::cerr << m_className << "::LoadGrid:\n"
815 << " Edge " << i << " is degenerate.\n";
816 return false;
817 }
818 }
819
820 // Get the "faces" (only for 3D maps).
821 struct Face {
822 // Indices of edges
823 int edge[4];
824 int type;
825 };
826 size_t nFaces = 0;
828 if (N == 3) {
829 while (std::getline(gridfile, line)) {
830 ++iLine;
831 ltrim(line);
832 if (line.empty()) continue;
833 // Find section 'Faces'.
834 if (line.substr(0, 5) != "Faces") continue;
835 // Get the number of faces (given in brackets).
837 std::cerr << m_className << "::LoadGrid:\n"
838 << " Could not read number of faces.\n";
839 return false;
840 }
842 data >> nFaces;
843 faces.resize(nFaces);
844 // Get the indices of the edges constituting this face.
845 for (size_t j = 0; j < nFaces; ++j) {
846 gridfile >> faces[j].type;
847 if (faces[j].type != 3 && faces[j].type != 4) {
848 std::cerr << m_className << "::LoadGrid:\n"
849 << " Face with index " << j
850 << " has invalid number of edges, " << faces[j].type << ".\n";
851 return false;
852 }
853 for (int k = 0; k < faces[j].type; ++k) {
854 gridfile >> faces[j].edge[k];
855 }
856 }
857 iLine += nFaces - 1;
858 break;
859 }
860 if (gridfile.eof()) {
861 std::cerr << m_className << "::LoadGrid:\n"
862 << " Could not find section 'Faces' in file\n"
863 << " " << filename << ".\n";
864 return false;
865 } else if (gridfile.fail()) {
866 PrintError(m_className + "::LoadGrid", filename, iLine);
867 return false;
868 }
869 }
870
871 // Get the elements.
872 size_t nElements = 0;
873 while (std::getline(gridfile, line)) {
874 ++iLine;
875 ltrim(line);
876 if (line.empty()) continue;
877 // Find section 'Elements'.
878 if (line.substr(0, 8) != "Elements") continue;
879 // Get number of elements (given in brackets).
881 std::cerr << m_className << "::LoadGrid:\n"
882 << " Could not read number of elements.\n";
883 return false;
884 }
886 data >> nElements;
887 data.clear();
888 // Resize the list of elements.
889 m_elements.resize(nElements);
890 // Get type and constituting edges of each element.
891 for (size_t j = 0; j < nElements; ++j) {
892 ++iLine;
893 unsigned int type = 0;
894 gridfile >> type;
895 if (N == 2) {
896 if (type == 0) {
897 // Point
898 unsigned int p = 0;
899 gridfile >> p;
900 // Make sure the index is not out of range.
901 if (p >= nVertices) {
902 PrintError(m_className + "::LoadGrid", filename, iLine);
903 std::cerr << " Vertex index out of range.\n";
904 return false;
905 }
906 m_elements[j].vertex[0] = p;
907 } else if (type == 1) {
908 // Line
909 for (size_t k = 0; k < 2; ++k) {
910 int p = 0;
911 gridfile >> p;
912 if (p < 0) p = -p - 1;
913 // Make sure the index is not out of range.
914 if (p >= (int)nVertices) {
915 PrintError(m_className + "::LoadGrid", filename, iLine);
916 std::cerr << " Vertex index out of range.\n";
917 return false;
918 }
919 m_elements[j].vertex[k] = p;
920 }
921 } else if (type == 2) {
922 // Triangle
923 int p0 = 0, p1 = 0, p2 = 0;
924 gridfile >> p0 >> p1 >> p2;
925 // Negative edge index means that the sequence of the two points
926 // is supposed to be inverted.
927 // The actual index is then given by "-index - 1".
928 if (p0 < 0) p0 = -p0 - 1;
929 if (p1 < 0) p1 = -p1 - 1;
930 if (p2 < 0) p2 = -p2 - 1;
931 // Make sure the indices are not out of range.
932 if (p0 >= (int)nEdges || p1 >= (int)nEdges || p2 >= (int)nEdges) {
933 PrintError(m_className + "::LoadGrid", filename, iLine);
934 std::cerr << " Edge index out of range.\n";
935 return false;
936 }
937 m_elements[j].vertex[0] = edgeP1[p0];
938 m_elements[j].vertex[1] = edgeP2[p0];
939 if (edgeP1[p1] != m_elements[j].vertex[0] &&
940 edgeP1[p1] != m_elements[j].vertex[1]) {
941 m_elements[j].vertex[2] = edgeP1[p1];
942 } else {
943 m_elements[j].vertex[2] = edgeP2[p1];
944 }
945 // Rearrange vertices such that point 0 is on the left.
946 while (m_vertices[m_elements[j].vertex[0]][0] >
947 m_vertices[m_elements[j].vertex[1]][0] ||
948 m_vertices[m_elements[j].vertex[0]][0] >
949 m_vertices[m_elements[j].vertex[2]][0]) {
950 const int tmp = m_elements[j].vertex[0];
951 m_elements[j].vertex[0] = m_elements[j].vertex[1];
952 m_elements[j].vertex[1] = m_elements[j].vertex[2];
953 m_elements[j].vertex[2] = tmp;
954 }
955 } else if (type == 3) {
956 // Rectangle
957 for (size_t k = 0; k < 4; ++k) {
958 int p = 0;
959 gridfile >> p;
960 // Make sure the index is not out of range.
961 if (p >= (int)nEdges || -p - 1 >= (int)nEdges) {
962 PrintError(m_className + "::LoadGrid", filename, iLine);
963 std::cerr << " Edge index out of range.\n";
964 return false;
965 }
966 if (p >= 0) {
967 m_elements[j].vertex[k] = edgeP1[p];
968 } else {
969 m_elements[j].vertex[k] = edgeP2[-p - 1];
970 }
971 }
972 // Rearrange vertices such that point 0 is on the left.
973 while (m_vertices[m_elements[j].vertex[0]][0] >
974 m_vertices[m_elements[j].vertex[1]][0] ||
975 m_vertices[m_elements[j].vertex[0]][0] >
976 m_vertices[m_elements[j].vertex[2]][0] ||
977 m_vertices[m_elements[j].vertex[0]][0] >
978 m_vertices[m_elements[j].vertex[3]][0]) {
979 const int tmp = m_elements[j].vertex[0];
980 m_elements[j].vertex[0] = m_elements[j].vertex[1];
981 m_elements[j].vertex[1] = m_elements[j].vertex[2];
982 m_elements[j].vertex[2] = m_elements[j].vertex[3];
983 m_elements[j].vertex[3] = tmp;
984 }
985 } else {
986 // Other element types are not permitted for 2d grids.
987 PrintError(m_className + "::LoadGrid", filename, iLine);
988 std::cerr << " Invalid element type (" << type
989 << ") for 2d mesh.\n";
990 return false;
991 }
992 } else if (N == 3) {
993 if (type == 2) {
994 // Triangle
995 int edge0, edge1, edge2;
996 gridfile >> edge0 >> edge1 >> edge2;
997 // Get the vertices.
998 // Negative edge index means that the sequence of the two points
999 // is supposed to be inverted.
1000 // The actual index is then given by "-index - 1".
1001 // For our purposes, the orientation does not matter.
1002 if (edge0 < 0) edge0 = -edge0 - 1;
1003 if (edge1 < 0) edge1 = -edge1 - 1;
1004 if (edge2 < 0) edge2 = -edge2 - 1;
1005 // Make sure the indices are not out of range.
1006 if (edge0 >= (int)nEdges || edge1 >= (int)nEdges ||
1007 edge2 >= (int)nEdges) {
1008 PrintError(m_className + "::LoadGrid", filename, iLine);
1009 std::cerr << " Edge index out of range.\n";
1010 return false;
1011 }
1012 m_elements[j].vertex[0] = edgeP1[edge0];
1013 m_elements[j].vertex[1] = edgeP2[edge0];
1014 if (edgeP1[edge1] != m_elements[j].vertex[0] &&
1015 edgeP1[edge1] != m_elements[j].vertex[1]) {
1016 m_elements[j].vertex[2] = edgeP1[edge1];
1017 } else {
1018 m_elements[j].vertex[2] = edgeP2[edge1];
1019 }
1020 } else if (type == 5) {
1021 // Tetrahedron
1022 // Get the faces.
1023 // Negative face index means that the sequence of the edges
1024 // is supposed to be inverted.
1025 // For our purposes, the orientation does not matter.
1026 int face0, face1, face2, face3;
1027 gridfile >> face0 >> face1 >> face2 >> face3;
1028 if (face0 < 0) face0 = -face0 - 1;
1029 if (face1 < 0) face1 = -face1 - 1;
1030 if (face2 < 0) face2 = -face2 - 1;
1031 if (face3 < 0) face3 = -face3 - 1;
1032 // Make sure the face indices are not out of range.
1033 if (face0 >= (int)nFaces || face1 >= (int)nFaces ||
1034 face2 >= (int)nFaces || face3 >= (int)nFaces) {
1035 PrintError(m_className + "::LoadGrid", filename, iLine);
1036 std::cerr << " Face index out of range.\n";
1037 return false;
1038 }
1039 // Get the edges of the first face.
1040 int edge0 = faces[face0].edge[0];
1041 int edge1 = faces[face0].edge[1];
1042 int edge2 = faces[face0].edge[2];
1043 if (edge0 < 0) edge0 = -edge0 - 1;
1044 if (edge1 < 0) edge1 = -edge1 - 1;
1045 if (edge2 < 0) edge2 = -edge2 - 1;
1046 // Make sure the edge indices are not out of range.
1047 if (edge0 >= (int)nEdges || edge1 >= (int)nEdges ||
1048 edge2 >= (int)nEdges) {
1049 PrintError(m_className + "::LoadGrid", filename, iLine);
1050 std::cerr << " Edge index out of range.\n";
1051 return false;
1052 }
1053 // Get the first three vertices.
1054 m_elements[j].vertex[0] = edgeP1[edge0];
1055 m_elements[j].vertex[1] = edgeP2[edge0];
1056 if (edgeP1[edge1] != m_elements[j].vertex[0] &&
1057 edgeP1[edge1] != m_elements[j].vertex[1]) {
1058 m_elements[j].vertex[2] = edgeP1[edge1];
1059 } else {
1060 m_elements[j].vertex[2] = edgeP2[edge1];
1061 }
1062 // Get the fourth vertex from face 1.
1063 edge0 = faces[face1].edge[0];
1064 edge1 = faces[face1].edge[1];
1065 edge2 = faces[face1].edge[2];
1066 if (edge0 < 0) edge0 = -edge0 - 1;
1067 if (edge1 < 0) edge1 = -edge1 - 1;
1068 if (edge2 < 0) edge2 = -edge2 - 1;
1069 const auto v0 = m_elements[j].vertex[0];
1070 const auto v1 = m_elements[j].vertex[1];
1071 const auto v2 = m_elements[j].vertex[2];
1072 if (edgeP1[edge0] != v0 && edgeP1[edge0] != v1 && edgeP1[edge0] != v2) {
1073 m_elements[j].vertex[3] = edgeP1[edge0];
1074 } else if (edgeP2[edge0] != v0 && edgeP2[edge0] != v1 &&
1075 edgeP2[edge0] != v2) {
1076 m_elements[j].vertex[3] = edgeP2[edge0];
1077 } else if (edgeP1[edge1] != v0 &&
1078 edgeP1[edge1] != v1 &&
1079 edgeP1[edge1] != v2) {
1080 m_elements[j].vertex[3] = edgeP1[edge1];
1081 } else if (edgeP2[edge1] != v0 &&
1082 edgeP2[edge1] != v1 &&
1083 edgeP2[edge1] != v2) {
1084 m_elements[j].vertex[3] = edgeP2[edge1];
1085 } else {
1086 PrintError(m_className + "::LoadGrid", filename, iLine);
1087 std::cerr << " Face 1 of element " << j << " is degenerate.\n";
1088 return false;
1089 }
1090 } else {
1091 // Other element types are not allowed.
1092 PrintError(m_className + "::LoadGrid", filename, iLine);
1093 if (type == 0 || type == 1) {
1094 std::cerr << " Invalid element type (" << type
1095 << ") for 3d mesh.\n";
1096 } else {
1097 std::cerr << " Element type " << type << " is not supported.\n"
1098 << " Remesh with option -t to create only"
1099 << " triangles and tetrahedra.\n";
1100 }
1101 return false;
1102 }
1103 }
1104 m_elements[j].type = type;
1105 m_elements[j].region = m_regions.size();
1106 }
1107 break;
1108 }
1109 if (gridfile.eof()) {
1110 std::cerr << m_className << "::LoadGrid:\n"
1111 << " Could not find section 'Elements' in file\n"
1112 << " " << filename << ".\n";
1113 return false;
1114 } else if (gridfile.fail()) {
1115 PrintError(m_className + "::LoadGrid", filename, iLine);
1116 return false;
1117 }
1118
1119 // Assign regions to elements.
1120 while (std::getline(gridfile, line)) {
1121 ltrim(line);
1122 if (line.empty()) continue;
1123 // Find section 'Region'.
1124 if (line.substr(0, 6) != "Region") continue;
1125 // Get region name (given in brackets).
1126 if (!ExtractFromBrackets(line)) {
1127 std::cerr << m_className << "::LoadGrid:\n"
1128 << " Could not read region name.\n";
1129 return false;
1130 }
1133 data >> name;
1134 data.clear();
1135 const size_t index = FindRegion(name);
1136 if (index >= m_regions.size()) {
1137 // Specified region name is not in the list.
1138 std::cerr << m_className << "::LoadGrid:\n"
1139 << " Unknown region " << name << ".\n";
1140 continue;
1141 }
1144 if (!ExtractFromBrackets(line)) {
1145 std::cerr << m_className << "::LoadGrid:\n"
1146 << " Could not read number of elements in region "
1147 << name << ".\n";
1148 return false;
1149 }
1150 int nElementsRegion;
1151 data.str(line);
1153 data.clear();
1154 for (int j = 0; j < nElementsRegion; ++j) {
1155 size_t iElement = 0;
1156 gridfile >> iElement;
1157 if (iElement >= m_elements.size()) {
1158 std::cerr << m_className << "::LoadGrid:\n"
1159 << " Error reading element indices for region "
1160 << name << ".\n";
1161 return false;
1162 }
1163 m_elements[iElement].region = index;
1164 }
1165 }
1166 if (gridfile.fail() && !gridfile.eof()) {
1167 std::cerr << m_className << "::LoadGrid:\n"
1168 << " Error reading file " << filename << ".\n";
1169 return false;
1170 }
1171 return true;
1172}
size_t FindRegion(const std::string &name) const

Referenced by Initialise().

◆ LoadWeightingField()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::LoadWeightingField ( const std::string & datafilename,
std::vector< std::array< double, N > > & wf,
std::vector< double > & wp )
protected

Definition at line 1498 of file ComponentTcadBase.cc.

1500 {
1501
1503 if (!datafile) {
1504 std::cerr << m_className << "::LoadWeightingField:\n"
1505 << " Could not open file " << filename << ".\n";
1506 return false;
1507 }
1508 const size_t nVertices = m_vertices.size();
1510 zeroes.fill(0.);
1511 bool ok = true;
1512 // Read the file line by line.
1514 while (std::getline(datafile, line)) {
1515 // Strip white space from the beginning of the line.
1516 ltrim(line);
1517 if (line.empty()) continue;
1518 // Find data section.
1519 if (line.substr(0, 8) != "function") continue;
1520 // Read type of data set.
1521 const auto pEq = line.find('=');
1522 if (pEq == std::string::npos) {
1523 // No "=" found.
1524 std::cerr << m_className << "::LoadWeightingField:\n"
1525 << " Error reading file " << filename << ".\n"
1526 << " Line:\n " << line << "\n";
1527 return false;
1528 }
1529 line = line.substr(pEq + 1);
1532 data >> dataset;
1533 data.clear();
1534 if (dataset != "ElectrostaticPotential" && dataset != "ElectricField") {
1535 continue;
1536 }
1537 bool field = false;
1538 if (dataset == "ElectricField") {
1539 if (wf.empty()) wf.assign(nVertices, zeroes);
1540 field = true;
1541 } else {
1542 if (wp.empty()) wp.assign(nVertices, 0.);
1543 }
1548 // Get the region name (given in brackets).
1550 std::cerr << m_className << "::LoadWeightingField:\n"
1551 << " Cannot extract region name.\n"
1552 << " Line:\n " << line << "\n";
1553 ok = false;
1554 break;
1555 }
1557 data.str(line);
1558 data >> name;
1559 data.clear();
1560 // Check if the region name matches one from the mesh file.
1561 const auto index = FindRegion(name);
1562 if (index >= m_regions.size()) {
1563 std::cerr << m_className << "::LoadWeightingField:\n"
1564 << " Unknown region " << name << ".\n";
1565 ok = false;
1566 break;
1567 }
1568 // Get the number of values.
1570 if (!ExtractFromBrackets(line)) {
1571 std::cerr << m_className << "::LoadWeightingField:\n"
1572 << " Cannot extract number of values to be read.\n"
1573 << " Line:\n " << line << "\n";
1574 ok = false;
1575 break;
1576 }
1577 int nValues;
1578 data.str(line);
1579 data >> nValues;
1580 data.clear();
1581 if (field) nValues /= N;
1582 // Mark the vertices belonging to this region.
1584 const size_t nElements = m_elements.size();
1585 for (size_t j = 0; j < nElements; ++j) {
1586 if (m_elements[j].region != index) continue;
1587 const unsigned int nV = ElementVertices(m_elements[j]);
1588 for (unsigned int k = 0; k < nV; ++k) {
1589 isInRegion[m_elements[j].vertex[k]] = true;
1590 }
1591 }
1592 unsigned int ivertex = 0;
1593 for (int j = 0; j < nValues; ++j) {
1594 // Read the next value.
1596 if (field) {
1597 for (size_t k = 0; k < N; ++k) datafile >> val[k];
1598 } else {
1599 datafile >> val[0];
1600 }
1601 // Find the next vertex belonging to the region.
1602 while (ivertex < nVertices) {
1603 if (isInRegion[ivertex]) break;
1604 ++ivertex;
1605 }
1606 // Check if there is a mismatch between the number of vertices
1607 // and the number of values.
1608 if (ivertex >= nVertices) {
1609 std::cerr << m_className << "::LoadWeightingField:\n"
1610 << " Dataset " << dataset
1611 << " has more values than vertices in region " << name << "\n";
1612 ok = false;
1613 break;
1614 }
1615 if (field) {
1616 wf[ivertex] = val;
1617 } else {
1618 wp[ivertex] = val[0];
1619 }
1620 ++ivertex;
1621 }
1622 }
1623
1624 if (!ok || (datafile.fail() && !datafile.eof())) {
1625 std::cerr << m_className << "::LoadWeightingField:\n"
1626 << " Error reading file " << filename << "\n";
1627 return false;
1628 }
1629 return true;
1630}

Referenced by SetWeightingField(), SetWeightingField(), and SetWeightingPotential().

◆ MapCoordinates()

template<size_t N>
void Garfield::ComponentTcadBase< N >::MapCoordinates ( std::array< double, N > & x,
std::array< bool, N > & mirr ) const
protected

Definition at line 1892 of file ComponentTcadBase.cc.

1893 {
1894 mirr.fill(false);
1895 for (size_t i = 0; i < N; ++i) {
1896 // In case of periodicity, reduce to the cell volume.
1897 const double cellsx = m_bbMax[i] - m_bbMin[i];
1898 if (m_periodic[i]) {
1899 x[i] = m_bbMin[i] + fmod(x[i] - m_bbMin[i], cellsx);
1900 if (x[i] < m_bbMin[i]) x[i] += cellsx;
1901 } else if (m_mirrorPeriodic[i]) {
1902 double xNew = m_bbMin[i] + fmod(x[i] - m_bbMin[i], cellsx);
1903 if (xNew < m_bbMin[i]) xNew += cellsx;
1904 const int nx = int(floor(0.5 + (xNew - x[i]) / cellsx));
1905 if (nx != 2 * (nx / 2)) {
1906 xNew = m_bbMin[i] + m_bbMax[i] - xNew;
1907 mirr[i] = true;
1908 }
1909 x[i] = xNew;
1910 }
1911 }
1912}
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.
Definition Component.hh:376
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
Definition Component.hh:374

◆ PrintRegions()

template<size_t N>
void Garfield::ComponentTcadBase< N >::PrintRegions ( ) const

List all currently defined regions.

Definition at line 1633 of file ComponentTcadBase.cc.

1633 {
1634
1635 if (m_regions.empty()) {
1636 std::cerr << m_className << "::PrintRegions:\n"
1637 << " No regions are currently defined.\n";
1638 return;
1639 }
1640
1641 const size_t nRegions = m_regions.size();
1642 std::cout << m_className << "::PrintRegions:\n"
1643 << " Currently " << nRegions << " regions are defined.\n"
1644 << " Index Name Material Medium\n";
1645 for (size_t i = 0; i < nRegions; ++i) {
1646 std::cout << std::setw(8) << std::right << i << " "
1647 << std::setw(20) << std::left << m_regions[i].name << " "
1648 << std::setw(18) << std::left << m_regions[i].material << " ";
1649 if (!m_regions[i].medium) {
1650 std::cout << std::setw(18) << "none";
1651 } else {
1652 std::cout << std::setw(18) << m_regions[i].medium->GetName();
1653 }
1654 if (m_regions[i].drift) {
1655 std::cout << " (active)\n";
1656 } else {
1657 std::cout << "\n";
1658 }
1659 }
1660}

◆ ReadDataset()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::ReadDataset ( std::ifstream & datafile,
const std::string & dataset )
protected

Definition at line 1302 of file ComponentTcadBase.cc.

1303 {
1304
1305 if (!datafile.is_open()) return false;
1306 enum DataSet {
1308 EField,
1311 eMobility,
1312 hMobility,
1313 eAlpha,
1314 hAlpha,
1315 eLifetime,
1316 hLifetime,
1319 Unknown
1320 };
1321 DataSet ds = Unknown;
1322 if (dataset == "ElectrostaticPotential") {
1324 } else if (dataset == "ElectricField") {
1325 ds = EField;
1326 } else if (dataset == "eDriftVelocity") {
1328 } else if (dataset == "hDriftVelocity") {
1330 } else if (dataset == "eMobility") {
1331 ds = eMobility;
1332 } else if (dataset == "hMobility") {
1333 ds = hMobility;
1334 } else if (dataset == "eAlphaAvalanche") {
1335 ds = eAlpha;
1336 } else if (dataset == "hAlphaAvalanche") {
1337 ds = hAlpha;
1338 } else if (dataset == "eLifetime") {
1339 ds = eLifetime;
1340 } else if (dataset == "hLifetime") {
1341 ds = hLifetime;
1342 } else if (dataset.substr(0, 14) == "TrapOccupation") {
1343 if (dataset.substr(17, 2) == "Do") {
1345 } else if (dataset.substr(17, 2) == "Ac") {
1347 }
1348 } else {
1349 std::cerr << m_className << "::ReadDataset:\n"
1350 << " Unexpected dataset " << dataset << ".\n";
1351 return false;
1352 }
1353 bool isVector = false;
1354 if (ds == EField || ds == eDriftVelocity || ds == hDriftVelocity) {
1355 isVector = true;
1356 }
1362 // Get the region name (given in brackets).
1364 std::cerr << m_className << "::ReadDataset:\n"
1365 << " Cannot extract region name.\n"
1366 << " Line:\n " << line << "\n";
1367 return false;
1368 }
1371 data >> name;
1372 data.clear();
1373 // Check if the region name matches one from the mesh file.
1374 const size_t index = FindRegion(name);
1375 if (index >= m_regions.size()) {
1376 std::cerr << m_className << "::ReadDataset:\n"
1377 << " Unknown region " << name << ".\n";
1378 return false;
1379 }
1380 if (m_debug) {
1381 std::cout << m_className << "::ReadDataset:\n"
1382 << " Reading dataset " << dataset << " for region "
1383 << name << ".\n";
1384 }
1385 // Get the number of values.
1387 if (!ExtractFromBrackets(line)) {
1388 std::cerr << m_className << "::ReadDataset:\n"
1389 << " Cannot extract number of values to be read.\n"
1390 << " Line:\n " << line << "\n";
1391 return false;
1392 }
1393 int nValues;
1394 data.str(line);
1395 data >> nValues;
1396 if (isVector) nValues /= N;
1397 if (m_debug) std::cout << " Expecting " << nValues << " values.\n";
1398 // Mark the vertices belonging to this region.
1399 const size_t nVertices = m_vertices.size();
1401 size_t nVerticesInRegion = 0;
1402 size_t nElementsInRegion = 0;
1403 for (const auto& element : m_elements) {
1404 if (element.region != index) continue;
1406 const unsigned int nV = ElementVertices(element);
1407 for (unsigned int k = 0; k < nV; ++k) {
1408 if (isInRegion[element.vertex[k]]) continue;
1409 isInRegion[element.vertex[k]] = true;
1411 }
1412 }
1413 if (m_debug) {
1414 std::cout << " Region has " << nElementsInRegion << " elements and "
1415 << nVerticesInRegion << " vertices.\n";
1416 }
1417 unsigned int ivertex = 0;
1418 for (int j = 0; j < nValues; ++j) {
1419 // Read the next value.
1421 if (isVector) {
1422 for (size_t k = 0; k < N; ++k) datafile >> val[k];
1423 } else {
1424 datafile >> val[0];
1425 }
1426 // Find the next vertex belonging to the region.
1427 while (ivertex < nVertices) {
1428 if (isInRegion[ivertex]) break;
1429 ++ivertex;
1430 }
1431 // Check if there is a mismatch between the number of m_vertices
1432 // and the number of potential values.
1433 if (ivertex >= nVertices) {
1434 std::cerr << m_className << "::ReadDataset:\n"
1435 << " Dataset " << dataset << " has more values than "
1436 << "there are vertices in region " << name << "\n";
1437 return false;
1438 }
1439
1440 switch (ds) {
1442 m_epot[ivertex] = val[0];
1443 break;
1444 case EField:
1445 for (size_t k = 0; k < N; ++k) m_efield[ivertex][k] = val[k];
1446 break;
1447 case eDriftVelocity:
1448 // Scale from cm/s to cm/ns.
1449 for (size_t k = 0; k < N; ++k) {
1450 m_eVelocity[ivertex][k] = val[k] * 1.e-9;
1451 }
1452 break;
1453 case hDriftVelocity:
1454 // Scale from cm/s to cm/ns.
1455 for (size_t k = 0; k < N; ++k) {
1456 m_hVelocity[ivertex][k] = val[k] * 1.e-9;
1457 }
1458 break;
1459 case eMobility:
1460 // Convert from cm2 / (V s) to cm2 / (V ns).
1461 m_eMobility[ivertex] = val[0] * 1.e-9;
1462 break;
1463 case hMobility:
1464 // Convert from cm2 / (V s) to cm2 / (V ns).
1465 m_hMobility[ivertex] = val[0] * 1.e-9;
1466 break;
1467 case eAlpha:
1468 m_eAlpha[ivertex] = val[0];
1469 break;
1470 case hAlpha:
1471 m_hAlpha[ivertex] = val[0];
1472 break;
1473 case eLifetime:
1474 // Convert from s to ns.
1475 m_eLifetime[ivertex] = val[0] * 1.e9;
1476 break;
1477 case hLifetime:
1478 // Convert from s to ns.
1479 m_hLifetime[ivertex] = val[0] * 1.e9;
1480 break;
1482 m_donorOcc[ivertex].push_back(val[0]);
1483 break;
1485 m_acceptorOcc[ivertex].push_back(val[0]);
1486 break;
1487 default:
1488 std::cerr << m_className << "::ReadDataset:\n"
1489 << " Unexpected dataset (" << ds << "). Program bug!\n";
1490 return false;
1491 }
1492 ++ivertex;
1493 }
1494 return true;
1495}

Referenced by LoadData().

◆ SetAcceptor()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetAcceptor ( const size_t acceptorNumber,
const double exsec,
const double hxsec,
const double concentration )

Set the properties of an acceptor-type defect state.

Definition at line 1744 of file ComponentTcadBase.cc.

1746 {
1747 if (acceptorNumber >= m_acceptors.size()) {
1748 std::cerr << m_className << "::SetAcceptor: Index out of range.\n";
1749 return false;
1750 }
1754
1756 return true;
1757}

◆ SetDonor()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetDonor ( const size_t donorNumber,
const double exsec,
const double hxsec,
const double concentration )

Set the properties of a donor-type defect state.

Parameters
donorNumberindex of the donor
exseccross-section [cm2] for electrons
hxseccross-section [cm2] for holes
concentrationdefect density [cm-3]

Definition at line 1728 of file ComponentTcadBase.cc.

1730 {
1731 if (donorNumber >= m_donors.size()) {
1732 std::cerr << m_className << "::SetDonor: Index out of range.\n";
1733 return false;
1734 }
1735 m_donors[donorNumber].xsece = eXsec;
1736 m_donors[donorNumber].xsech = hXsec;
1737 m_donors[donorNumber].conc = conc;
1738
1740 return true;
1741}

◆ SetDriftRegion()

template<size_t N>
void Garfield::ComponentTcadBase< N >::SetDriftRegion ( const size_t ireg)

Make a region active ("driftable").

Definition at line 1674 of file ComponentTcadBase.cc.

1674 {
1675 if (i >= m_regions.size()) {
1676 std::cerr << m_className << "::SetDriftRegion: Index out of range.\n";
1677 return;
1678 }
1679 m_regions[i].drift = true;
1680}

◆ SetMedium() [1/2]

template<size_t N>
void Garfield::ComponentTcadBase< N >::SetMedium ( const size_t ireg,
Medium * m )

Set the medium to be associated to a given region.

Definition at line 1692 of file ComponentTcadBase.cc.

1692 {
1693 if (i >= m_regions.size()) {
1694 std::cerr << m_className << "::SetMedium: Index out of range.\n";
1695 return;
1696 }
1697 if (!medium) {
1698 std::cerr << m_className << "::SetMedium: Null pointer.\n";
1699 return;
1700 }
1701 m_regions[i].medium = medium;
1702}

Referenced by main().

◆ SetMedium() [2/2]

template<size_t N>
void Garfield::ComponentTcadBase< N >::SetMedium ( const std::string & material,
Medium * m )

Set the medium to be associated to all regions with a given material.

Definition at line 1705 of file ComponentTcadBase.cc.

1706 {
1707 if (!medium) {
1708 std::cerr << m_className << "::SetMedium: Null pointer.\n";
1709 return;
1710 }
1711 size_t nMatch = 0;
1712 const auto nRegions = m_regions.size();
1713 for (size_t i = 0; i < nRegions; ++i) {
1714 if (material != m_regions[i].material) continue;
1715 m_regions[i].medium = medium;
1716 std::cout << m_className << "::SetMedium: Associating region " << i
1717 << " (" << m_regions[i].name << ") with "
1718 << medium->GetName() << ".\n";
1719 ++nMatch;
1720 }
1721 if (nMatch == 0) {
1722 std::cerr << m_className << "::SetMedium: Found no region with material "
1723 << material << ".\n";
1724 }
1725}

◆ SetWeightingField() [1/2]

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetWeightingField ( const std::string & datfile1,
const std::string & datfile2,
const double dv,
const double t,
const std::string & label )

Import time-dependent weighting fields at t > 0.

Definition at line 497 of file ComponentTcadBase.cc.

499 {
500
501 if (!m_ready) {
502 std::cerr << m_className << "::SetWeightingField:\n"
503 << " Mesh is not available. Call Initialise first.\n";
504 return false;
505 }
506 if (dv < Small) {
507 std::cerr << m_className << "::SetWeightingField:\n"
508 << " Voltage difference must be > 0.\n";
509 return false;
510 }
511 const double s = 1. / dv;
512
513 if (m_wlabel.empty()) {
514 std::cerr << m_className << "::SetWeightingField:\n"
515 << " Prompt component not present.\n"
516 << " Import the map for t = 0 first.\n";
517 return false;
518 }
519 if (label != m_wlabel.front()) {
520 std::cerr << m_className << "::SetWeightingField:\n"
521 << " Label does not match the existing prompt component.\n";
522 return false;
523 }
524
525 // Load the first map.
529 std::cerr << m_className << "::SetWeightingField:\n"
530 << " Could not import data from " << datfile1 << ".\n";
531 return false;
532 }
533 // Load the second map.
537 std::cerr << m_className << "::SetWeightingField:\n"
538 << " Could not import data from " << datfile2 << ".\n";
539 return false;
540 }
541 const size_t nVertices = m_vertices.size();
542 if (wf1.size() != nVertices || wf2.size() != nVertices) {
543 std::cerr << m_className << "::SetWeightingField:\n"
544 << " Could not load electric field values.\n";
545 return false;
546 }
547 if (m_wfield.size() != nVertices) {
548 std::cerr << m_className << "::SetWeightingField:\n"
549 << " Prompt weighting field not present.\n";
550 return false;
551 }
553 wf.resize(nVertices);
554 for (size_t i = 0; i < nVertices; ++i) {
555 for (size_t j = 0; j < N; ++j) {
556 wf[i][j] = (wf2[i][j] - wf1[i][j]) * s;
557 }
558 }
559 if (m_dwtf.empty() || t > m_dwtf.back()) {
560 m_dwtf.push_back(t);
561 m_dwf.push_back(std::move(wf));
562 } else {
563 const auto it = std::upper_bound(m_dwtf.begin(), m_dwtf.end(), t);
564 const auto n = std::distance(m_dwtf.begin(), it);
565 m_dwtf.insert(it, t);
566 m_dwf.insert(m_dwf.begin() + n, std::move(wf));
567 }
568 return true;
569}
bool LoadWeightingField(const std::string &datafilename, std::vector< std::array< double, N > > &wf, std::vector< double > &wp)

◆ SetWeightingField() [2/2]

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetWeightingField ( const std::string & datfile1,
const std::string & datfile2,
const double dv,
const std::string & label )

Import field maps defining the prompt weighting field and potential.

Parameters
datfile1.dat file containing the field map at nominal bias.
datfile2.dat file containing the field map for a configuration with the potential at the electrode to be read out increased by a small voltage dv.
dvincrease in electrode potential between the two field maps.
labelname of the electrode

The field maps must use the same mesh as the drift field.

Definition at line 350 of file ComponentTcadBase.cc.

353 {
354
355 if (!m_ready) {
356 std::cerr << m_className << "::SetWeightingField:\n"
357 << " Mesh is not available. Call Initialise first.\n";
358 return false;
359 }
360 if (dv < Small) {
361 std::cerr << m_className << "::SetWeightingField:\n"
362 << " Voltage difference must be > 0.\n";
363 return false;
364 }
365 const double s = 1. / dv;
366 m_wfield.clear();
367 m_wpot.clear();
368 m_wlabel.clear();
369 m_wshift.clear();
370
371 // Load first the field/potential at nominal bias.
375 std::cerr << m_className << "::SetWeightingField:\n"
376 << " Could not import data from " << datfile1 << ".\n";
377 return false;
378 }
379
380 // Then load the field/potential for the configuration with the potential
381 // at the electrode to be read out increased by small voltage dv.
385 std::cerr << m_className << "::SetWeightingField:\n"
386 << " Could not import data from " << datfile2 << ".\n";
387 return false;
388 }
389 const size_t nVertices = m_vertices.size();
390 bool foundField = true;
391 if (wf1.size() != nVertices || wf2.size() != nVertices) {
392 foundField = false;
393 std::cerr << m_className << "::SetWeightingField:\n"
394 << " Could not load electric field values.\n";
395 }
396 bool foundPotential = true;
397 if (wp1.size() != nVertices || wp2.size() != nVertices) {
398 foundPotential = false;
399 std::cerr << m_className << "::SetWeightingField:\n"
400 << " Could not load electrostatic potentials.\n";
401 }
402 if (!foundField && !foundPotential) return false;
403 if (foundField) {
404 m_wfield.resize(nVertices);
405 for (size_t i = 0; i < nVertices; ++i) {
406 for (size_t j = 0; j < N; ++j) {
407 m_wfield[i][j] = (wf2[i][j] - wf1[i][j]) * s;
408 }
409 }
410 }
411 if (foundPotential) {
412 m_wpot.assign(nVertices, 0.);
413 for (size_t i = 0; i < nVertices; ++i) {
414 m_wpot[i] = (wp2[i] - wp1[i]) * s;
415 }
416 }
417 m_wlabel.push_back(label);
418 m_wshift.push_back({0., 0., 0.});
419 return true;
420}

◆ SetWeightingFieldShift()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetWeightingFieldShift ( const std::string & label,
const double x,
const double y,
const double z )

Shift the maps of weighting field/potential for a given electrode with respect to the original mesh. If the electrode does not exist yet, a new one will be added to the list.

Definition at line 572 of file ComponentTcadBase.cc.

573 {
574 if (m_wlabel.empty()) {
575 std::cerr << m_className << "::SetWeightingFieldShift:\n"
576 << " No map of weighting potentials/fields loaded.\n";
577 return false;
578 }
579 const size_t n = m_wlabel.size();
580 for (size_t i = 0; i < n; ++i) {
581 if (m_wlabel[i] == label) {
582 m_wshift[i] = {x, y, z};
583 std::cout << m_className << "::SetWeightingFieldShift:\n"
584 << " Changing offset of electrode \'" << label
585 << "\' to (" << x << ", " << y << ", " << z << ") cm.\n";
586 return true;
587 }
588 }
589 m_wlabel.push_back(label);
590 m_wshift.push_back({x, y, z});
591 std::cout << m_className << "::SetWeightingFieldShift:\n"
592 << " Adding electrode \'" << label << "\' with offset ("
593 << x << ", " << y << ", " << z << ") cm.\n";
594 return true;
595}

◆ SetWeightingPotential()

template<size_t N>
bool Garfield::ComponentTcadBase< N >::SetWeightingPotential ( const std::string & datfile1,
const std::string & datfile2,
const double dv,
const double t,
const std::string & label )

Import time-dependent weighting potentials at t > 0.

Definition at line 423 of file ComponentTcadBase.cc.

425 {
426
427 if (!m_ready) {
428 std::cerr << m_className << "::SetWeightingPotential:\n"
429 << " Mesh is not available. Call Initialise first.\n";
430 return false;
431 }
432 if (dv < Small) {
433 std::cerr << m_className << "::SetWeightingPotential:\n"
434 << " Voltage difference must be > 0.\n";
435 return false;
436 }
437 const double s = 1. / dv;
438
439 if (m_wlabel.empty()) {
440 std::cerr << m_className << "::SetWeightingPotential:\n"
441 << " Prompt component not present.\n"
442 << " Import the map for t = 0 first.\n";
443 return false;
444 }
445 if (label != m_wlabel.front()) {
446 std::cerr << m_className << "::SetWeightingPotential:\n"
447 << " Label does not match the existing prompt component.\n";
448 return false;
449 }
450
451 // Load the first map.
455 std::cerr << m_className << "::SetWeightingPotential:\n"
456 << " Could not import data from " << datfile1 << ".\n";
457 return false;
458 }
459 // Load the second map.
463 std::cerr << m_className << "::SetWeightingPotential:\n"
464 << " Could not import data from " << datfile2 << ".\n";
465 return false;
466 }
467 const size_t nVertices = m_vertices.size();
468 if (wp1.size() != nVertices || wp2.size() != nVertices) {
469 std::cerr << m_className << "::SetWeightingPotential:\n"
470 << " Could not load electrostatic potentials.\n";
471 return false;
472 }
473 if (m_wpot.size() != nVertices) {
474 std::cerr << m_className << "::SetWeightingPotential:\n"
475 << " Prompt weighting potential not present.\n";
476 return false;
477 }
479 for (size_t i = 0; i < nVertices; ++i) {
480 wp[i] = (wp2[i] - wp1[i]) * s;
481 // Subtract the prompt component.
482 wp[i] -= m_wpot[i];
483 }
484 if (m_dwtp.empty() || t > m_dwtp.back()) {
485 m_dwtp.push_back(t);
486 m_dwp.push_back(std::move(wp));
487 } else {
488 const auto it = std::upper_bound(m_dwtp.begin(), m_dwtp.end(), t);
489 const auto n = std::distance(m_dwtp.begin(), it);
490 m_dwtp.insert(it, t);
491 m_dwp.insert(m_dwp.begin() + n, std::move(wp));
492 }
493 return true;
494}

◆ UnsetDriftRegion()

template<size_t N>
void Garfield::ComponentTcadBase< N >::UnsetDriftRegion ( const size_t ireg)

Make a region inactive.

Definition at line 1683 of file ComponentTcadBase.cc.

1683 {
1684 if (i >= m_regions.size()) {
1685 std::cerr << m_className << "::UnsetDriftRegion: Index out of range.\n";
1686 return;
1687 }
1688 m_regions[i].drift = false;
1689}

◆ UpdateAttachment()

template<size_t N>
void Garfield::ComponentTcadBase< N >::UpdateAttachment ( )
protected

Definition at line 1924 of file ComponentTcadBase.cc.

1924 {
1925
1926 if (m_vertices.empty()) return;
1927 const size_t nVertices = m_vertices.size();
1928 m_eAttachment.assign(nVertices, 0.);
1929 m_hAttachment.assign(nVertices, 0.);
1930
1931 const size_t nAcceptors = m_acceptors.size();
1932 for (size_t i = 0; i < nAcceptors; ++i) {
1933 const auto& defect = m_acceptors[i];
1934 if (defect.conc < 0.) continue;
1935 for (size_t j = 0; j < nVertices; ++j) {
1936 // Get the occupation probability.
1937 const double f = m_acceptorOcc[j][i];
1938 if (defect.xsece > 0.) {
1939 m_eAttachment[j] += defect.conc * defect.xsece * (1. - f);
1940 }
1941 if (defect.xsech > 0.) {
1942 m_hAttachment[j] += defect.conc * defect.xsech * f;
1943 }
1944 }
1945 }
1946 const size_t nDonors = m_donors.size();
1947 for (size_t i = 0; i < nDonors; ++i) {
1948 const auto& defect = m_donors[i];
1949 if (defect.conc < 0.) continue;
1950 for (size_t j = 0; j < nVertices; ++j) {
1951 const double f = m_donorOcc[j][i];
1952 if (defect.xsece > 0.) {
1953 m_eAttachment[j] += defect.conc * defect.xsece * f;
1954 }
1955 if (defect.xsech > 0.) {
1956 m_hAttachment[j] += defect.conc * defect.xsech * (1. - f);
1957 }
1958 }
1959 }
1960}

Referenced by SetAcceptor(), and SetDonor().

◆ UpdatePeriodicity()

template<size_t N>
void Garfield::ComponentTcadBase< N >::UpdatePeriodicity ( )
overrideprotectedvirtual

Verify periodicities.

Implements Garfield::Component.

Definition at line 1826 of file ComponentTcadBase.cc.

1826 {
1827 if (!m_ready) {
1828 std::cerr << m_className << "::UpdatePeriodicity:\n"
1829 << " Field map not available.\n";
1830 return;
1831 }
1832
1833 // Check for conflicts.
1834 for (size_t i = 0; i < 3; ++i) {
1835 if (m_periodic[i] && m_mirrorPeriodic[i]) {
1836 std::cerr << m_className << "::UpdatePeriodicity:\n"
1837 << " Both simple and mirror periodicity requested. Reset.\n";
1838 m_periodic[i] = m_mirrorPeriodic[i] = false;
1839 }
1840 if (m_axiallyPeriodic[i]) {
1841 std::cerr << m_className << "::UpdatePeriodicity:\n"
1842 << " Axial symmetry is not supported. Reset.\n";
1843 m_axiallyPeriodic.fill(false);
1844 }
1845 if (m_rotationSymmetric[i]) {
1846 std::cerr << m_className << "::UpdatePeriodicity:\n"
1847 << " Rotation symmetry is not supported. Reset.\n";
1848 m_rotationSymmetric.fill(false);
1849 }
1850 }
1851}
std::array< bool, 3 > m_rotationSymmetric
Rotation symmetry around x-axis, y-axis, z-axis.
Definition Component.hh:380
std::array< bool, 3 > m_axiallyPeriodic
Axial periodicity in x, y, z.
Definition Component.hh:378

◆ WeightingField()

template<size_t N>
void Garfield::ComponentTcadBase< N >::WeightingField ( const double x,
const double y,
const double z,
double & wx,
double & wy,
double & wz,
const std::string & label )
overridevirtual

Calculate the weighting field at a given point and for a given electrode.

Parameters
x,y,zcoordinates [cm].
wx,wy,wzcomponents of the weighting field [1/cm].
labelname of the electrode

Reimplemented from Garfield::Component.

Definition at line 49 of file ComponentTcadBase.cc.

51 {
52 wx = wy = wz = 0.;
53 if (m_wfield.empty()) {
54 std::cerr << m_className << "::WeightingField: Not available.\n";
55 return;
56 }
57 double dx = 0., dy = 0., dz = 0.;
58 if (!GetOffset(label, dx, dy, dz)) return;
59 Interpolate(x - dx, y - dy, z - dz, m_wfield, wx, wy, wz);
60}

◆ WeightingPotential()

template<size_t N>
double Garfield::ComponentTcadBase< N >::WeightingPotential ( const double x,
const double y,
const double z,
const std::string & label )
overridevirtual

Calculate the weighting potential at a given point.

Parameters
x,y,zcoordinates [cm].
labelname of the electrode.
Returns
weighting potential [dimensionless].

Reimplemented from Garfield::Component.

Definition at line 63 of file ComponentTcadBase.cc.

65 {
66
67 if (m_wpot.empty()) {
68 std::cerr << m_className << "::WeightingPotential: Not available.\n";
69 return 0.;
70 }
71 double dx = 0., dy = 0., dz = 0.;
72 if (!GetOffset(label, dx, dy, dz)) return 0.;
73 double v = 0.;
74 Interpolate(x - dx, y - dy, z - dz, m_wpot, v);
75 return v;
76}

Member Data Documentation

◆ m_acceptorOcc

template<size_t N>
std::vector<std::vector<float> > Garfield::ComponentTcadBase< N >::m_acceptorOcc
protected

Definition at line 238 of file ComponentTcadBase.hh.

Referenced by Cleanup(), ReadDataset(), and UpdateAttachment().

◆ m_acceptors

template<size_t N>
std::vector<Defect> Garfield::ComponentTcadBase< N >::m_acceptors
protected

◆ m_bbMax

template<size_t N>
std::array<double, 3> Garfield::ComponentTcadBase< N >::m_bbMax = {{0., 0., 0.}}
protected

Definition at line 263 of file ComponentTcadBase.hh.

263{{0., 0., 0.}};

Referenced by InBoundingBox(), Initialise(), and MapCoordinates().

◆ m_bbMin

template<size_t N>
std::array<double, 3> Garfield::ComponentTcadBase< N >::m_bbMin = {{0., 0., 0.}}
protected

Definition at line 262 of file ComponentTcadBase.hh.

262{{0., 0., 0.}};

Referenced by InBoundingBox(), Initialise(), and MapCoordinates().

◆ m_donorOcc

template<size_t N>
std::vector<std::vector<float> > Garfield::ComponentTcadBase< N >::m_donorOcc
protected

Definition at line 237 of file ComponentTcadBase.hh.

Referenced by Cleanup(), ReadDataset(), and UpdateAttachment().

◆ m_donors

template<size_t N>
std::vector<Defect> Garfield::ComponentTcadBase< N >::m_donors
protected

◆ m_dwf

template<size_t N>
std::vector<std::vector<std::array<double, N> > > Garfield::ComponentTcadBase< N >::m_dwf
protected

Definition at line 218 of file ComponentTcadBase.hh.

Referenced by Cleanup(), and SetWeightingField().

◆ m_dwp

template<size_t N>
std::vector<std::vector<double> > Garfield::ComponentTcadBase< N >::m_dwp
protected

Definition at line 219 of file ComponentTcadBase.hh.

Referenced by Cleanup(), and SetWeightingPotential().

◆ m_dwtf

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_dwtf
protected

Definition at line 221 of file ComponentTcadBase.hh.

Referenced by Cleanup(), and SetWeightingField().

◆ m_dwtp

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_dwtp
protected

Definition at line 222 of file ComponentTcadBase.hh.

Referenced by Cleanup(), and SetWeightingPotential().

◆ m_eAlpha

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_eAlpha
protected

◆ m_eAttachment

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_eAttachment
protected

Definition at line 240 of file ComponentTcadBase.hh.

Referenced by Cleanup(), ElectronAttachment(), and UpdateAttachment().

◆ m_efield

template<size_t N>
std::vector<std::array<double, N> > Garfield::ComponentTcadBase< N >::m_efield
protected

Definition at line 208 of file ComponentTcadBase.hh.

Referenced by Cleanup(), Initialise(), LoadData(), and ReadDataset().

◆ m_elements

template<size_t N>
std::vector<Element> Garfield::ComponentTcadBase< N >::m_elements
protected

◆ m_eLifetime

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_eLifetime
protected

Definition at line 234 of file ComponentTcadBase.hh.

Referenced by Cleanup(), GetElectronLifetime(), Initialise(), LoadData(), and ReadDataset().

◆ m_eMobility

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_eMobility
protected

Definition at line 228 of file ComponentTcadBase.hh.

Referenced by Cleanup(), GetElectronMobility(), Initialise(), LoadData(), and ReadDataset().

◆ m_epot

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_epot
protected

Definition at line 206 of file ComponentTcadBase.hh.

Referenced by Cleanup(), Initialise(), LoadData(), and ReadDataset().

◆ m_eVelocity

template<size_t N>
std::vector<std::array<double, N> > Garfield::ComponentTcadBase< N >::m_eVelocity
protected

◆ m_hAlpha

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_hAlpha
protected

◆ m_hAttachment

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_hAttachment
protected

Definition at line 241 of file ComponentTcadBase.hh.

Referenced by Cleanup(), HoleAttachment(), and UpdateAttachment().

◆ m_hLifetime

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_hLifetime
protected

Definition at line 235 of file ComponentTcadBase.hh.

Referenced by Cleanup(), GetHoleLifetime(), Initialise(), LoadData(), and ReadDataset().

◆ m_hMobility

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_hMobility
protected

Definition at line 229 of file ComponentTcadBase.hh.

Referenced by Cleanup(), GetHoleMobility(), Initialise(), LoadData(), and ReadDataset().

◆ m_hVelocity

template<size_t N>
std::vector<std::array<double, N> > Garfield::ComponentTcadBase< N >::m_hVelocity
protected

◆ m_pMax

template<size_t N>
double Garfield::ComponentTcadBase< N >::m_pMax = 0.
protected

Definition at line 267 of file ComponentTcadBase.hh.

Referenced by GetVoltageRange(), and Initialise().

◆ m_pMin

template<size_t N>
double Garfield::ComponentTcadBase< N >::m_pMin = 0.
protected

Definition at line 266 of file ComponentTcadBase.hh.

Referenced by GetVoltageRange(), and Initialise().

◆ m_regions

◆ m_useAlphaMap

template<size_t N>
bool Garfield::ComponentTcadBase< N >::m_useAlphaMap = false
protected

Definition at line 259 of file ComponentTcadBase.hh.

Referenced by EnableAlphaMap(), and HasTownsendMap().

◆ m_useAttachmentMap

template<size_t N>
bool Garfield::ComponentTcadBase< N >::m_useAttachmentMap = false
protected

Definition at line 257 of file ComponentTcadBase.hh.

Referenced by EnableAttachmentMap(), and HasAttachmentMap().

◆ m_useVelocityMap

template<size_t N>
bool Garfield::ComponentTcadBase< N >::m_useVelocityMap = false
protected

Definition at line 255 of file ComponentTcadBase.hh.

Referenced by EnableVelocityMap(), and HasVelocityMap().

◆ m_vertices

◆ m_wfield

template<size_t N>
std::vector<std::array<double, N> > Garfield::ComponentTcadBase< N >::m_wfield
protected

Definition at line 211 of file ComponentTcadBase.hh.

Referenced by Cleanup(), SetWeightingField(), and SetWeightingField().

◆ m_wlabel

template<size_t N>
std::vector<std::string> Garfield::ComponentTcadBase< N >::m_wlabel
protected

◆ m_wpot

template<size_t N>
std::vector<double> Garfield::ComponentTcadBase< N >::m_wpot
protected

Definition at line 212 of file ComponentTcadBase.hh.

Referenced by Cleanup(), SetWeightingField(), and SetWeightingPotential().

◆ m_wshift

template<size_t N>
std::vector<std::array<double, 3> > Garfield::ComponentTcadBase< N >::m_wshift
protected

Definition at line 215 of file ComponentTcadBase.hh.

Referenced by Cleanup(), SetWeightingField(), and SetWeightingFieldShift().

◆ nMaxVertices

template<size_t N>
size_t Garfield::ComponentTcadBase< N >::nMaxVertices = 4
staticconstexprprotected

Definition at line 160 of file ComponentTcadBase.hh.


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