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

Interpolation in a two-dimensional field map created by Sentaurus Device. More...

#include <ComponentTcad2d.hh>

+ Inheritance diagram for Garfield::ComponentTcad2d:

Public Member Functions

 ComponentTcad2d ()
 
 ~ComponentTcad2d ()
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)
 
void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
 
MediumGetMedium (const double x, const double y, const double z)
 Get the medium at a given location (x, y, z).
 
bool GetVoltageRange (double &vmin, double &vmax)
 Calculate the voltage range [V].
 
bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 Get the bounding box coordinates.
 
void SetRangeZ (const double zmin, const double zmax)
 
bool Initialise (const std::string &gridfilename, const std::string &datafilename)
 
void PrintRegions () const
 
unsigned int GetNumberOfRegions () const
 
void GetRegion (const unsigned int i, std::string &name, bool &active) const
 
void SetDriftRegion (const unsigned int ireg)
 
void UnsetDriftRegion (const unsigned int ireg)
 
void SetMedium (const unsigned int ireg, Medium *m)
 
MediumGetMedium (const unsigned int ireg) const
 
unsigned int GetNumberOfElements () const
 
bool GetElement (const unsigned int i, double &vol, double &dmin, double &dmax, int &type) const
 
bool GetElement (const unsigned int i, double &vol, double &dmin, double &dmax, int &type, int &node1, int &node2, int &node3, int &node4, int &reg) const
 
unsigned int GetNumberOfNodes () const
 
bool GetNode (const unsigned int i, double &x, double &y, double &v, double &ex, double &ey) const
 
bool GetMobility (const double x, const double y, const double z, double &emob, double &hmob)
 
void ElectronVelocity (const double x, const double y, const double z, double &vx, double &vy, double &vz, Medium *&m, int &status)
 Get the electron drift velocity.
 
void HoleVelocity (const double x, const double y, const double z, double &vx, double &vy, double &vz, Medium *&m, int &status)
 Get the hole drift velocity.
 
bool GetElectronLifetime (const double x, const double y, const double z, double &etau)
 
bool GetHoleLifetime (const double x, const double y, const double z, double &htau)
 
int GetNumberOfDonors ()
 
int GetNumberOfAcceptors ()
 
bool GetDonorOccupation (const double x, const double y, const double z, const unsigned int donorNumber, double &occupationFraction)
 
bool GetAcceptorOccupation (const double x, const double y, const double z, const unsigned int acceptorNumber, double &occupationFraction)
 
bool SetDonor (const unsigned int donorNumber, const double eXsec, const double hxSec, const double concentration)
 
bool SetAcceptor (const unsigned int acceptorNumber, const double eXsec, const double hxSec, const double concentration)
 
bool ElectronAttachment (const double x, const double y, const double z, double &eta)
 Get the electron attachment coefficient.
 
bool HoleAttachment (const double x, const double y, const double z, double &eta)
 Get the hole attachment coefficient.
 
- Public Member Functions inherited from Garfield::ComponentBase
 ComponentBase ()
 Constructor.
 
virtual ~ComponentBase ()
 Destructor.
 
virtual void SetGeometry (GeometryBase *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
 
virtual bool GetVoltageRange (double &vmin, double &vmax)=0
 Calculate the voltage range [V].
 
virtual void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
 
virtual double WeightingPotential (const double x, const double y, const double z, const std::string &label)
 
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 IsWireCrossed (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
 
virtual bool IsInTrapRadius (const double q0, const double x0, const double y0, const double z0, double &xw, double &yw, double &rw)
 
void EnablePeriodicityX (const bool on=true)
 Enable simple periodicity in the $x$ direction.
 
void DisablePeriodicityX ()
 
void EnablePeriodicityY (const bool on=true)
 Enable simple periodicity in the $y$ direction.
 
void DisablePeriodicityY ()
 
void EnablePeriodicityZ (const bool on=true)
 Enable simple periodicity in the $z$ direction.
 
void DisablePeriodicityZ ()
 
void EnableMirrorPeriodicityX (const bool on=true)
 Enable mirror periodicity in the $x$ direction.
 
void DisableMirrorPeriodicityX ()
 
void EnableMirrorPeriodicityY (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void DisableMirrorPeriodicityY ()
 
void EnableMirrorPeriodicityZ (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void DisableMirrorPeriodicityZ ()
 
void EnableAxialPeriodicityX (const bool on=true)
 Enable axial periodicity in the $x$ direction.
 
void DisableAxialPeriodicityX ()
 
void EnableAxialPeriodicityY (const bool on=true)
 Enable axial periodicity in the $y$ direction.
 
void DisableAxialPeriodicityY ()
 
void EnableAxialPeriodicityZ (const bool on=true)
 Enable axial periodicity in the $z$ direction.
 
void DisableAxialPeriodicityZ ()
 
void EnableRotationSymmetryX (const bool on=true)
 Enable rotation symmetry around the $x$ axis.
 
void DisableRotationSymmetryX ()
 
void EnableRotationSymmetryY (const bool on=true)
 Enable rotation symmetry around the $y$ axis.
 
void DisableRotationSymmetryY ()
 
void EnableRotationSymmetryZ (const bool on=true)
 Enable rotation symmetry around the $z$ axis.
 
void DisableRotationSymmetryZ ()
 
void EnableDebugging ()
 Switch on debugging messages.
 
void DisableDebugging ()
 Switch off debugging messages.
 
void ActivateTraps ()
 Request trapping to be taken care of by the component (for TCAD).
 
void DeactivateTraps ()
 
bool IsTrapActive ()
 
void ActivateVelocityMap ()
 Request velocity to be taken care of by the component (for TCAD).
 
void DectivateVelocityMap ()
 
bool IsVelocityActive ()
 
virtual bool ElectronAttachment (const double, const double, const double, double &eta)
 Get the electron attachment coefficient.
 
virtual bool HoleAttachment (const double, const double, const double, double &eta)
 Get the hole attachment coefficient.
 
virtual void ElectronVelocity (const double, const double, const double, double &vx, double &vy, double &vz, Medium *&, int &status)
 Get the electron drift velocity.
 
virtual void HoleVelocity (const double, const double, const double, double &vx, double &vy, double &vz, Medium *&, int &status)
 Get the hole drift velocity.
 
virtual bool GetElectronLifetime (const double, const double, const double, double &etau)
 
virtual bool GetHoleLifetime (const double, const double, const double, double &htau)
 

Additional Inherited Members

virtual void Reset ()=0
 Geometry checks.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 
- Protected Attributes inherited from Garfield::ComponentBase
std::string m_className
 Class name.
 
GeometryBasem_geometry
 Pointer to the geometry.
 
bool m_ready
 Ready for use?
 
bool m_activeTraps
 Does the component have traps?
 
bool m_hasVelocityMap
 Does the component have velocity maps?
 
bool m_xPeriodic
 Simple periodicity in x.
 
bool m_yPeriodic
 Simple periodicity in y.
 
bool m_zPeriodic
 Simple periodicity in z.
 
bool m_xMirrorPeriodic
 Mirror periodicity in x.
 
bool m_yMirrorPeriodic
 Mirror periodicity in y.
 
bool m_zMirrorPeriodic
 Mirror periodicity in z.
 
bool m_xAxiallyPeriodic
 Axial periodicity in x.
 
bool m_yAxiallyPeriodic
 Axial periodicity in y.
 
bool m_zAxiallyPeriodic
 Axial periodicity in z.
 
bool m_xRotationSymmetry
 Rotation symmetry around x-axis.
 
bool m_yRotationSymmetry
 Rotation symmetry around y-axis.
 
bool m_zRotationSymmetry
 Rotation symmetry around z-axis.
 
double m_bx0
 
double m_by0
 
double m_bz0
 
bool m_debug
 Switch on/off debugging messages.
 

Detailed Description

Interpolation in a two-dimensional field map created by Sentaurus Device.

Definition at line 10 of file ComponentTcad2d.hh.

Constructor & Destructor Documentation

◆ ComponentTcad2d()

Garfield::ComponentTcad2d::ComponentTcad2d ( )

Definition at line 21 of file ComponentTcad2d.cc.

21 : ComponentBase(),
22 m_hasPotential(false),
23 m_hasField(false),
24 m_hasElectronMobility(false),
25 m_hasHoleMobility(false),
26 m_hasElectronVelocity(false),
27 m_hasHoleVelocity(false),
28 m_hasElectronLifetime(false),
29 m_hasHoleLifetime(false),
30 m_validTraps(false),
31 m_pMin(0.),
32 m_pMax(0.),
33 m_hasRangeZ(false),
34 m_lastElement(0) {
35
36 m_className = "ComponentTcad2d";
37
38 m_regions.reserve(10);
39 m_vertices.reserve(10000);
40 m_elements.reserve(10000);
41}
ComponentBase()
Constructor.
Definition: ComponentBase.cc:6
std::string m_className
Class name.

◆ ~ComponentTcad2d()

Garfield::ComponentTcad2d::~ComponentTcad2d ( )
inline

Definition at line 16 of file ComponentTcad2d.hh.

16{}

Member Function Documentation

◆ ElectricField() [1/2]

void Garfield::ComponentTcad2d::ElectricField ( const double  x,
const double  y,
const double  z,
double &  ex,
double &  ey,
double &  ez,
double &  v,
Medium *&  m,
int &  status 
)
virtual

Implements Garfield::ComponentBase.

Definition at line 157 of file ComponentTcad2d.cc.

160 {
161
162 // Initialise.
163 ex = ey = ez = p = 0.;
164 m = NULL;
165
166 // Make sure the field map has been loaded.
167 if (!m_ready) {
168 std::cerr << m_className << "::ElectricField:\n"
169 << " Field map is not available for interpolation.\n";
170 status = -10;
171 return;
172 }
173
174 // In case of periodicity, reduce to the cell volume.
175 double x = xin, y = yin, z = zin;
176 bool xmirr = false, ymirr = false;
177 MapCoordinates(x, y, xmirr, ymirr);
178 // Check if the point is inside the bounding box.
179 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
180 status = -11;
181 return;
182 }
183 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
184 status = -11;
185 return;
186 }
187
188 // Assume this will work.
189 status = 0;
190 double w[nMaxVertices] = {0};
191 if (m_lastElement >= 0) {
192 // Check if the point is still located in the previously found element.
193 const Element& last = m_elements[m_lastElement];
194 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
195 if (CheckElement(x, y, last, w)) {
196 const unsigned int nVertices = last.type + 1;
197 for (unsigned int j = 0; j < nVertices; ++j) {
198 const Vertex& vj = m_vertices[last.vertex[j]];
199 ex += w[j] * vj.ex;
200 ey += w[j] * vj.ey;
201 p += w[j] * vj.p;
202 }
203 if (xmirr) ex = -ex;
204 if (ymirr) ey = -ey;
205 m = m_regions[last.region].medium;
206 if (!m_regions[last.region].drift || !m) status = -5;
207 return;
208 }
209 }
210 // The point is not in the previous element.
211 // Check the adjacent elements.
212 const unsigned int nNeighbours = last.neighbours.size();
213 for (unsigned int i = 0; i < nNeighbours; ++i) {
214 const Element& element = m_elements[last.neighbours[i]];
215 if (x < element.xmin || x > element.xmax ||
216 y < element.ymin || y > element.ymax) continue;
217 if (!CheckElement(x, y, element, w)) continue;
218 const unsigned int nVertices = element.type + 1;
219 for (unsigned int j = 0; j < nVertices; ++j) {
220 const Vertex& vj = m_vertices[element.vertex[j]];
221 ex += w[j] * vj.ex;
222 ey += w[j] * vj.ey;
223 p += w[j] * vj.p;
224 }
225 if (xmirr) ex = -ex;
226 if (ymirr) ey = -ey;
227 m = m_regions[element.region].medium;
228 if (!m_regions[element.region].drift || !m) status = -5;
229 m_lastElement = last.neighbours[i];
230 return;
231 }
232 }
233
234 // The point is not in the previous element nor in the adjacent ones.
235 // We have to loop over all elements.
236 const unsigned int nElements = m_elements.size();
237 for (unsigned int i = 0; i < nElements; ++i) {
238 const Element& element = m_elements[i];
239 if (x < element.xmin || x > element.xmax ||
240 y < element.ymin || y > element.ymax) continue;
241 if (!CheckElement(x, y, element, w)) continue;
242 const unsigned int nVertices = element.type + 1;
243 for (unsigned int j = 0; j < nVertices; ++j) {
244 const Vertex& vj = m_vertices[element.vertex[j]];
245 ex += w[j] * vj.ex;
246 ey += w[j] * vj.ey;
247 p += w[j] * vj.p;
248 }
249 if (xmirr) ex = -ex;
250 if (ymirr) ey = -ey;
251 m = m_regions[element.region].medium;
252 if (!m_regions[element.region].drift || !m) status = -5;
253 m_lastElement = i;
254 return;
255 }
256 // Point is outside the mesh.
257 if (m_debug) {
258 std::cerr << m_className << "::ElectricField:\n"
259 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
260 }
261 status = -6;
262}
bool m_ready
Ready for use?
bool m_debug
Switch on/off debugging messages.

Referenced by ElectricField(), and WeightingField().

◆ ElectricField() [2/2]

void Garfield::ComponentTcad2d::ElectricField ( const double  x,
const double  y,
const double  z,
double &  ex,
double &  ey,
double &  ez,
Medium *&  m,
int &  status 
)
inlinevirtual

Calculate the drift field at given point.

Parameters
x,y,zcoordinates [cm].
ex,ey,ezcomponents of the electric field [V/cm].
mpointer to the medium at this location.
statusstatus flag

Status flags:

        0: Inside an active medium
      > 0: Inside a wire of type X
-4 ... -1: On the side of a plane where no wires are
       -5: Inside the mesh but not in an active medium
       -6: Outside the mesh
      -10: Unknown potential type (should not occur)
    other: Other cases (should not occur)

Implements Garfield::ComponentBase.

Definition at line 22 of file ComponentTcad2d.hh.

23 {
24
25 double v = 0.;
26 ElectricField(x, y, z, ex, ey, ez, v, m, status);
27 }
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)

◆ ElectronAttachment()

bool Garfield::ComponentTcad2d::ElectronAttachment ( const double  ,
const double  ,
const double  ,
double &  eta 
)
virtual

Get the electron attachment coefficient.

Reimplemented from Garfield::ComponentBase.

Definition at line 79 of file ComponentTcad2d.cc.

80 {
81 eta = 0.;
82 if (!m_validTraps) {
83 std::cerr << m_className << "::ElectronAttachment:\n"
84 << " Trap cross-sections or concentrations are invalid.\n";
85 return false;
86 }
87
88 if (m_donors.empty() && m_acceptors.empty()) {
89 if (m_debug) {
90 std::cerr << m_className << "::ElectronAttachment:\n"
91 << " There are no traps defined.\n";
92 }
93 return true;
94 }
95
96 const unsigned int nAcceptors = m_acceptors.size();
97 for (unsigned int i = 0; i < nAcceptors; ++i) {
98 const Defect& acceptor = m_acceptors[i];
99 double f = 0.;
100 GetAcceptorOccupation(x, y, z, i, f);
101 eta += acceptor.conc * acceptor.xsece * (1. - f);
102 }
103 const unsigned int nDonors = m_donors.size();
104 for (unsigned int i = 0; i < nDonors; ++i) {
105 const Defect& donor = m_donors[i];
106 double f = 0.;
107 GetDonorOccupation(x, y, z, i, f);
108 eta += donor.conc * donor.xsece * f;
109 }
110 return true;
111}
bool GetDonorOccupation(const double x, const double y, const double z, const unsigned int donorNumber, double &occupationFraction)
bool GetAcceptorOccupation(const double x, const double y, const double z, const unsigned int acceptorNumber, double &occupationFraction)

◆ ElectronVelocity()

void Garfield::ComponentTcad2d::ElectronVelocity ( const double  ,
const double  ,
const double  ,
double &  vx,
double &  vy,
double &  vz,
Medium *&  ,
int &  status 
)
virtual

Get the electron drift velocity.

Reimplemented from Garfield::ComponentBase.

Definition at line 264 of file ComponentTcad2d.cc.

267 {
268
269 // Initialise.
270 vx = vy = vz = 0.;
271 m = NULL;
272 // Make sure the field map has been loaded.
273 if (!m_ready) {
274 std::cerr << m_className << "::ElectronVelocity:\n";
275 std::cerr << " Field map is not available for interpolation.\n";
276 status = -10;
277 return;
278 }
279
280 double x = xin, y = yin, z = zin;
281 // In case of periodicity, reduce to the cell volume.
282 bool xmirr = false, ymirr = false;
283 MapCoordinates(x, y, xmirr, ymirr);
284 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
285 status = -11;
286 return;
287 }
288 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
289 status = -11;
290 return;
291 }
292
293 // Assume this will work.
294 status = 0;
295 double w[nMaxVertices] = {0};
296 if (m_lastElement >= 0) {
297 // Check if the point is still located in the previously found element.
298 const Element& last = m_elements[m_lastElement];
299 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
300 if (CheckElement(x, y, last, w)) {
301 const unsigned int nVertices = last.type + 1;
302 for (unsigned int j = 0; j < nVertices; ++j) {
303 const Vertex& vj = m_vertices[last.vertex[j]];
304 vx += w[j] * vj.eVx;
305 vy += w[j] * vj.eVy;
306 }
307 if (xmirr) vx = -vx;
308 if (ymirr) vy = -vy;
309 m = m_regions[last.region].medium;
310 if (!m_regions[last.region].drift || !m) status = -5;
311 return;
312 }
313 }
314 // The point is not in the previous element.
315 // Check the adjacent elements.
316 const unsigned int nNeighbours = last.neighbours.size();
317 for (unsigned int i = 0; i < nNeighbours; ++i) {
318 const Element& element = m_elements[last.neighbours[i]];
319 if (x < element.xmin || x > element.xmax ||
320 y < element.ymin || y > element.ymax) continue;
321 if (!CheckElement(x, y, element, w)) continue;
322 const unsigned int nVertices = element.type + 1;
323 for (unsigned int j = 0; j < nVertices; ++j) {
324 const Vertex& vj = m_vertices[element.vertex[j]];
325 vx += w[j] * vj.eVx;
326 vy += w[j] * vj.eVy;
327 }
328 if (xmirr) vx = -vx;
329 if (ymirr) vy = -vy;
330 m = m_regions[element.region].medium;
331 if (!m_regions[element.region].drift || !m) status = -5;
332 m_lastElement = last.neighbours[i];
333 return;
334 }
335 }
336
337 // The point is not in the previous element nor in the adjacent ones.
338 // We have to loop over all elements.
339 const unsigned int nElements = m_elements.size();
340 for (unsigned int i = 0; i < nElements; ++i) {
341 const Element& element = m_elements[i];
342 if (x < element.xmin || x > element.xmax ||
343 y < element.ymin || y > element.ymax) continue;
344 if (!CheckElement(x, y, element, w)) continue;
345 const unsigned int nVertices = element.type + 1;
346 for (unsigned int j = 0; j < nVertices; ++j) {
347 const Vertex& vj = m_vertices[element.vertex[j]];
348 vx += w[j] * vj.eVx;
349 vy += w[j] * vj.eVy;
350 }
351 if (xmirr) vx = -vx;
352 if (ymirr) vy = -vy;
353 m = m_regions[element.region].medium;
354 if (!m_regions[element.region].drift || !m) status = -5;
355 m_lastElement = i;
356 return;
357 }
358 // Point is outside the mesh.
359 if (m_debug) {
360 std::cerr << m_className << "::ElectronVelocity:\n"
361 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
362 }
363 status = -6;
364}

◆ GetAcceptorOccupation()

bool Garfield::ComponentTcad2d::GetAcceptorOccupation ( const double  x,
const double  y,
const double  z,
const unsigned int  acceptorNumber,
double &  occupationFraction 
)

Definition at line 859 of file ComponentTcad2d.cc.

862 {
863 f = 0.;
864 if (acceptorNumber >= m_acceptors.size()) {
865 std::cerr << m_className << "::GetAcceptorOccupation:\n"
866 << " Acceptor " << acceptorNumber << " does not exist.\n";
867 return false;
868 }
869
870 // Make sure the field map has been loaded.
871 if (!m_ready) {
872 std::cerr << m_className << "::GetAcceptorOccupation:\n"
873 << " Field map is not available for interpolation.\n";
874 return false;
875 }
876
877 double x = xin, y = yin, z = zin;
878 // In case of periodicity, reduce to the cell volume.
879 bool xmirr = false, ymirr = false;
880 MapCoordinates(x, y, xmirr, ymirr);
881 // Check if the point is inside the bounding box.
882 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
883 return false;
884 }
885 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
886 return false;
887 }
888
889
890 double w[nMaxVertices] = {0};
891 if (m_lastElement >= 0) {
892 // Check if the point is still located in the previously found element.
893 const Element& last = m_elements[m_lastElement];
894 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
895 if (CheckElement(x, y, last, w)) {
896 const unsigned int nVertices = last.type + 1;
897 for (unsigned int j = 0; j < nVertices; ++j) {
898 const Vertex& vj = m_vertices[last.vertex[j]];
899 f += w[j] * vj.acceptorOcc[acceptorNumber];
900 }
901 return true;
902 }
903 }
904 // The point is not in the previous element.
905 // Check the adjacent elements.
906 const unsigned int nNeighbours = last.neighbours.size();
907 for (unsigned int i = 0; i < nNeighbours; ++i) {
908 const Element& element = m_elements[last.neighbours[i]];
909 if (x < element.xmin || x > element.xmax ||
910 y < element.ymin || y > element.ymax) continue;
911 if (!CheckElement(x, y, element, w)) continue;
912 const unsigned int nVertices = element.type + 1;
913 for (unsigned int j = 0; j < nVertices; ++j) {
914 const Vertex& vj = m_vertices[element.vertex[j]];
915 f += w[j] * vj.acceptorOcc[acceptorNumber];
916 }
917 m_lastElement = last.neighbours[i];
918 return true;
919 }
920 }
921
922 // The point is not in the previous element nor in the adjacent ones.
923 // We have to loop over all elements.
924 const unsigned int nElements = m_elements.size();
925 for (unsigned int i = 0; i < nElements; ++i) {
926 const Element& element = m_elements[i];
927 if (x < element.xmin || x > element.xmax ||
928 y < element.ymin || y > element.ymax) continue;
929 if (!CheckElement(x, y, element, w)) continue;
930 const unsigned int nVertices = element.type + 1;
931 for (unsigned int j = 0; j < nVertices; ++j) {
932 const Vertex& vj = m_vertices[element.vertex[j]];
933 f += w[j] * vj.acceptorOcc[acceptorNumber];
934 }
935 m_lastElement = i;
936 return true;
937 }
938
939 // Point is outside the mesh.
940 if (m_debug) {
941 std::cerr << m_className << "::GetAcceptorOccupation:\n"
942 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
943 }
944 return false;
945}

Referenced by ElectronAttachment(), and HoleAttachment().

◆ GetBoundingBox()

bool Garfield::ComponentTcad2d::GetBoundingBox ( double &  xmin,
double &  ymin,
double &  zmin,
double &  xmax,
double &  ymax,
double &  zmax 
)
virtual

Get the bounding box coordinates.

Reimplemented from Garfield::ComponentBase.

Definition at line 1176 of file ComponentTcad2d.cc.

1177 {
1178
1179 if (!m_ready) return false;
1181 xmin = -INFINITY;
1182 xmax = +INFINITY;
1183 } else {
1184 xmin = m_xMinBB;
1185 xmax = m_xMaxBB;
1186 }
1187
1189 ymin = -INFINITY;
1190 ymax = +INFINITY;
1191 } else {
1192 ymin = m_yMinBB;
1193 ymax = m_yMaxBB;
1194 }
1195
1196 if (m_hasRangeZ) {
1197 zmin = m_zMinBB;
1198 zmax = m_zMaxBB;
1199 }
1200 return true;
1201}
bool m_yPeriodic
Simple periodicity in y.
bool m_yMirrorPeriodic
Mirror periodicity in y.
bool m_xPeriodic
Simple periodicity in x.
bool m_xMirrorPeriodic
Mirror periodicity in x.

◆ GetDonorOccupation()

bool Garfield::ComponentTcad2d::GetDonorOccupation ( const double  x,
const double  y,
const double  z,
const unsigned int  donorNumber,
double &  occupationFraction 
)

Definition at line 772 of file ComponentTcad2d.cc.

775 {
776 f = 0.;
777 if (donorNumber >= m_donors.size()) {
778 std::cerr << m_className << "::GetDonorOccupation:\n"
779 << " Donor " << donorNumber << " does not exist.\n";
780 return false;
781 }
782
783 // Make sure the field map has been loaded.
784 if (!m_ready) {
785 std::cerr << m_className << "::GetDonorOccupation:\n"
786 << " Field map is not available for interpolation.\n";
787 return false;
788 }
789
790 double x = xin, y = yin, z = zin;
791 // In case of periodicity, reduce to the cell volume.
792 bool xmirr = false, ymirr = false;
793 MapCoordinates(x, y, xmirr, ymirr);
794 // Check if the point is inside the bounding box.
795 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
796 return false;
797 }
798 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
799 return false;
800 }
801
802 double w[nMaxVertices] = {0};
803 if (m_lastElement >= 0) {
804 // Check if the point is still located in the previously found element.
805 const Element& last = m_elements[m_lastElement];
806 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
807 if (CheckElement(x, y, last, w)) {
808 const unsigned int nVertices = last.type + 1;
809 for (unsigned int j = 0; j < nVertices; ++j) {
810 const Vertex& vj = m_vertices[last.vertex[j]];
811 f += w[j] * vj.donorOcc[donorNumber];
812 }
813 return true;
814 }
815 }
816 // The point is not in the previous element.
817 // Check the adjacent elements.
818 const unsigned int nNeighbours = last.neighbours.size();
819 for (unsigned int i = 0; i < nNeighbours; ++i) {
820 const Element& element = m_elements[last.neighbours[i]];
821 if (x < element.xmin || x > element.xmax ||
822 y < element.ymin || y > element.ymax) continue;
823 if (!CheckElement(x, y, element, w)) continue;
824 const unsigned int nVertices = element.type + 1;
825 for (unsigned int j = 0; j < nVertices; ++j) {
826 const Vertex& vj = m_vertices[element.vertex[j]];
827 f += w[j] * vj.donorOcc[donorNumber];
828 }
829 m_lastElement = last.neighbours[i];
830 return true;
831 }
832 }
833
834 // The point is not in the previous element nor in the adjacent ones.
835 // We have to loop over all elements.
836 const unsigned int nElements = m_elements.size();
837 for (unsigned int i = 0; i < nElements; ++i) {
838 const Element& element = m_elements[i];
839 if (x < element.xmin || x > element.xmax ||
840 y < element.ymin || y > element.ymax) continue;
841 if (!CheckElement(x, y, element, w)) continue;
842 const unsigned int nVertices = element.type + 1;
843 for (unsigned int j = 0; j < nVertices; ++j) {
844 const Vertex& vj = m_vertices[element.vertex[j]];
845 f += w[j] * vj.donorOcc[donorNumber];
846 }
847 m_lastElement = i;
848 return true;
849 }
850
851 // Point is outside the mesh.
852 if (m_debug) {
853 std::cerr << m_className << "::GetDonorOccupation:\n"
854 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
855 }
856 return false;
857}

Referenced by ElectronAttachment(), and HoleAttachment().

◆ GetElectronLifetime()

bool Garfield::ComponentTcad2d::GetElectronLifetime ( const double  x,
const double  y,
const double  z,
double &  etau 
)
virtual

Reimplemented from Garfield::ComponentBase.

Definition at line 530 of file ComponentTcad2d.cc.

531 {
532
533 tau = 0.;
534 // Make sure the field map has been loaded.
535 if (!m_ready) {
536 std::cerr << m_className << "::GetElectronLifetime:\n"
537 << " Field map is not available for interpolation.\n";
538 return false;
539 }
540
541 double x = xin, y = yin, z = zin;
542 // In case of periodicity, reduce to the cell volume.
543 bool xmirr = false, ymirr = false;
544 MapCoordinates(x, y, xmirr, ymirr);
545 // Check if the point is inside the bounding box.
546 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
547 return false;
548 }
549 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) return false;
550
551 double w[nMaxVertices] = {0};
552 if (m_lastElement >= 0) {
553 // Check if the point is still located in the previously found element.
554 const Element& last = m_elements[m_lastElement];
555 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
556 if (CheckElement(x, y, last, w)) {
557 const unsigned int nVertices = last.type + 1;
558 for (unsigned int j = 0; j < nVertices; ++j) {
559 const Vertex& vj = m_vertices[last.vertex[j]];
560 tau += w[j] * vj.eTau;
561 }
562 return true;
563 }
564 }
565 // The point is not in the previous element.
566 // Check the adjacent elements.
567 const unsigned int nNeighbours = last.neighbours.size();
568 for (unsigned int i = 0; i < nNeighbours; ++i) {
569 const Element& element = m_elements[last.neighbours[i]];
570 if (x < element.xmin || x > element.xmax ||
571 y < element.ymin || y > element.ymax) continue;
572 if (!CheckElement(x, y, element, w)) continue;
573 const unsigned int nVertices = element.type + 1;
574 for (unsigned int j = 0; j < nVertices; ++j) {
575 const Vertex& vj = m_vertices[element.vertex[j]];
576 tau += w[j] * vj.eTau;
577 }
578 m_lastElement = last.neighbours[i];
579 return true;
580 }
581 }
582
583 // The point is not in the previous element nor in the adjacent ones.
584 // We have to loop over all elements.
585 const unsigned int nElements = m_elements.size();
586 for (unsigned int i = 0; i < nElements; ++i) {
587 const Element& element = m_elements[i];
588 if (x < element.xmin || x > element.xmax ||
589 y < element.ymin || y > element.ymax) continue;
590 if (!CheckElement(x, y, element, w)) continue;
591 const unsigned int nVertices = element.type + 1;
592 for (unsigned int j = 0; j < nVertices; ++j) {
593 const Vertex& vj = m_vertices[element.vertex[j]];
594 tau += w[j] * vj.eTau;
595 }
596 m_lastElement = i;
597 return true;
598 }
599
600 // Point is outside the mesh.
601 if (m_debug) {
602 std::cerr << m_className << "::GetElectronLifetime:\n"
603 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
604 }
605 return false;
606
607}

◆ GetElement() [1/2]

bool Garfield::ComponentTcad2d::GetElement ( const unsigned int  i,
double &  vol,
double &  dmin,
double &  dmax,
int &  type 
) const

Definition at line 1316 of file ComponentTcad2d.cc.

1317 {
1318
1319 if (i >= m_elements.size()) {
1320 std::cerr << m_className << "::GetElement:\n"
1321 << " Element index (" << i << ") out of range.\n";
1322 return false;
1323 }
1324
1325 const Element& element = m_elements[i];
1326 if (element.type == 1) {
1327 const Vertex& v0 = m_vertices[element.vertex[0]];
1328 const Vertex& v1 = m_vertices[element.vertex[1]];
1329 const double dx = v1.x - v0.x;
1330 const double dy = v1.y - v0.y;
1331 const double d = sqrt(dx * dx + dy * dy);
1332 dmin = dmax = vol = d;
1333 } else if (m_elements[i].type == 2) {
1334 const Vertex& v0 = m_vertices[element.vertex[0]];
1335 const Vertex& v1 = m_vertices[element.vertex[1]];
1336 const Vertex& v2 = m_vertices[element.vertex[2]];
1337 vol = 0.5 * fabs((v2.x - v0.x) * (v1.y - v0.y) -
1338 (v2.y - v0.y) * (v1.x - v0.x));
1339 const double a = sqrt(pow(v1.x - v0.x, 2) + pow(v1.y - v0.y, 2));
1340 const double b = sqrt(pow(v2.x - v0.x, 2) + pow(v2.y - v0.y, 2));
1341 const double c = sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2));
1342 dmin = std::min(std::min(a, b), c);
1343 dmax = std::max(std::max(a, b), c);
1344 } else if (m_elements[i].type == 3) {
1345 const Vertex& v0 = m_vertices[element.vertex[0]];
1346 const Vertex& v1 = m_vertices[element.vertex[1]];
1347 const Vertex& v3 = m_vertices[element.vertex[3]];
1348 const double a = sqrt(pow(v1.x - v0.x, 2) + pow(v1.y - v0.y, 2));
1349 const double b = sqrt(pow(v3.x - v0.x, 2) + pow(v3.y - v0.y, 2));
1350 vol = a * b;
1351 dmin = std::min(a, b);
1352 dmax = sqrt(a * a + b * b);
1353 } else {
1354 std::cerr << m_className << "::GetElement:\n"
1355 << " Unexpected element type (" << type << ")\n";
1356 return false;
1357 }
1358 return true;
1359}
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:337
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

Referenced by GetElement().

◆ GetElement() [2/2]

bool Garfield::ComponentTcad2d::GetElement ( const unsigned int  i,
double &  vol,
double &  dmin,
double &  dmax,
int &  type,
int &  node1,
int &  node2,
int &  node3,
int &  node4,
int &  reg 
) const

Definition at line 1361 of file ComponentTcad2d.cc.

1364 {
1365
1366 if (!GetElement(i, vol, dmin, dmax, type)) return false;
1367 const Element& element = m_elements[i];
1368 node1 = element.vertex[0];
1369 node2 = element.vertex[1];
1370 node3 = element.vertex[2];
1371 node4 = element.vertex[3];
1372 reg = element.region;
1373 return true;
1374}
bool GetElement(const unsigned int i, double &vol, double &dmin, double &dmax, int &type) const

◆ GetHoleLifetime()

bool Garfield::ComponentTcad2d::GetHoleLifetime ( const double  x,
const double  y,
const double  z,
double &  htau 
)
virtual

Reimplemented from Garfield::ComponentBase.

Definition at line 608 of file ComponentTcad2d.cc.

609 {
610
611 tau = 0.;
612 // Make sure the field map has been loaded.
613 if (!m_ready) {
614 std::cerr << m_className << "::GetHoleLifetime:\n"
615 << " Field map is not available for interpolation.\n";
616 return false;
617 }
618
619 double x = xin, y = yin, z = zin;
620 // In case of periodicity, reduce to the cell volume.
621 bool xmirr = false, ymirr = false;
622 MapCoordinates(x, y, xmirr, ymirr);
623 // Check if the point is inside the bounding box.
624 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
625 return false;
626 }
627 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) return false;
628
629 double w[nMaxVertices] = {0};
630 if (m_lastElement >= 0) {
631 // Check if the point is still located in the previously found element.
632 const Element& last = m_elements[m_lastElement];
633 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
634 if (CheckElement(x, y, last, w)) {
635 const unsigned int nVertices = last.type + 1;
636 for (unsigned int j = 0; j < nVertices; ++j) {
637 const Vertex& vj = m_vertices[last.vertex[j]];
638 tau += w[j] * vj.hTau;
639 }
640 return true;
641 }
642 }
643 // The point is not in the previous element.
644 // Check the adjacent elements.
645 const unsigned int nNeighbours = last.neighbours.size();
646 for (unsigned int i = 0; i < nNeighbours; ++i) {
647 const Element& element = m_elements[last.neighbours[i]];
648 if (x < element.xmin || x > element.xmax ||
649 y < element.ymin || y > element.ymax) continue;
650 if (!CheckElement(x, y, element, w)) continue;
651 const unsigned int nVertices = element.type + 1;
652 for (unsigned int j = 0; j < nVertices; ++j) {
653 const Vertex& vj = m_vertices[element.vertex[j]];
654 tau += w[j] * vj.hTau;
655 }
656 m_lastElement = last.neighbours[i];
657 return true;
658 }
659 }
660
661 // The point is not in the previous element nor in the adjacent ones.
662 // We have to loop over all elements.
663 const unsigned int nElements = m_elements.size();
664 for (unsigned int i = 0; i < nElements; ++i) {
665 const Element& element = m_elements[i];
666 if (x < element.xmin || x > element.xmax ||
667 y < element.ymin || y > element.ymax) continue;
668 if (!CheckElement(x, y, element, w)) continue;
669 const unsigned int nVertices = element.type + 1;
670 for (unsigned int j = 0; j < nVertices; ++j) {
671 const Vertex& vj = m_vertices[element.vertex[j]];
672 tau += w[j] * vj.hTau;
673 }
674 m_lastElement = i;
675 return true;
676 }
677
678 // Point is outside the mesh.
679 if (m_debug) {
680 std::cerr << m_className << "::GetHoleLifetime:\n"
681 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
682 }
683 return false;
684
685}

◆ GetMedium() [1/2]

Medium * Garfield::ComponentTcad2d::GetMedium ( const double  x,
const double  y,
const double  z 
)
virtual

Get the medium at a given location (x, y, z).

Reimplemented from Garfield::ComponentBase.

Definition at line 471 of file ComponentTcad2d.cc.

472 {
473
474 // Make sure the field map has been loaded.
475 if (!m_ready) {
476 std::cerr << m_className << "::GetMedium:\n"
477 << " Field map not available for interpolation.\n";
478 return NULL;
479 }
480
481 double x = xin, y = yin, z = zin;
482 // In case of periodicity, reduce to the cell volume.
483 bool xmirr = false, ymirr = false;
484 MapCoordinates(x, y, xmirr, ymirr);
485 // Check if the point is inside the bounding box.
486 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
487 return NULL;
488 }
489 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) return NULL;
490
491 // Shape functions
492 double w[nMaxVertices] = {0};
493 if (m_lastElement >= 0) {
494 // Check if the point is still located in the previously found element.
495 const Element& last = m_elements[m_lastElement];
496 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax &&
497 CheckElement(x, y, last, w)) {
498 return m_regions[last.region].medium;
499 }
500
501 // The point is not in the previous element.
502 // Check the adjacent elements.
503 const unsigned int nNeighbours = last.neighbours.size();
504 for (unsigned int i = 0; i < nNeighbours; ++i) {
505 const Element& element = m_elements[last.neighbours[i]];
506 if (x < element.xmin || x > element.xmax ||
507 y < element.ymin || y > element.ymax) continue;
508 if (!CheckElement(x, y, element, w)) continue;
509 m_lastElement = last.neighbours[i];
510 return m_regions[element.region].medium;
511 }
512 }
513
514 // The point is not in the previous element nor in the adjacent ones.
515 // We have to loop over all elements.
516 const unsigned int nElements = m_elements.size();
517 for (unsigned int i = 0; i < nElements; ++i) {
518 const Element& element = m_elements[i];
519 if (x < element.xmin || x > element.xmax ||
520 y < element.ymin || y > element.ymax) continue;
521 if (!CheckElement(x, y, element, w)) continue;
522 m_lastElement = i;
523 return m_regions[element.region].medium;
524 }
525
526 // Point is outside the mesh.
527 return NULL;
528}

◆ GetMedium() [2/2]

Medium * Garfield::ComponentTcad2d::GetMedium ( const unsigned int  ireg) const

Definition at line 1305 of file ComponentTcad2d.cc.

1305 {
1306
1307 if (i >= m_regions.size()) {
1308 std::cerr << m_className << "::GetMedium:\n"
1309 << " Region " << i << " does not exist.\n";
1310 return NULL;
1311 }
1312
1313 return m_regions[i].medium;
1314}

◆ GetMobility()

bool Garfield::ComponentTcad2d::GetMobility ( const double  x,
const double  y,
const double  z,
double &  emob,
double &  hmob 
)

Definition at line 687 of file ComponentTcad2d.cc.

689 {
690
691 emob = hmob = 0.;
692
693 // Make sure the field map has been loaded.
694 if (!m_ready) {
695 std::cerr << m_className << "::GetMobility:\n"
696 << " Field map is not available for interpolation.\n";
697 return false;
698 }
699
700 double x = xin, y = yin, z = zin;
701 // In case of periodicity, reduce to the cell volume.
702 bool xmirr = false, ymirr = false;
703 MapCoordinates(x, y, xmirr, ymirr);
704 // Check if the point is inside the bounding box.
705 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
706 return false;
707 }
708 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
709 return false;
710 }
711
712 double w[nMaxVertices] = {0};
713 if (m_lastElement >= 0) {
714 // Check if the point is still located in the previously found element.
715 const Element& last = m_elements[m_lastElement];
716 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
717 if (CheckElement(x, y, last, w)) {
718 const unsigned int nVertices = last.type + 1;
719 for (unsigned int j = 0; j < nVertices; ++j) {
720 const Vertex& vj = m_vertices[last.vertex[j]];
721 emob += w[j] * vj.emob;
722 hmob += w[j] * vj.hmob;
723 }
724 return true;
725 }
726 }
727 // The point is not in the previous element.
728 // Check the adjacent elements.
729 const unsigned int nNeighbours = last.neighbours.size();
730 for (unsigned int i = 0; i < nNeighbours; ++i) {
731 const Element& element = m_elements[last.neighbours[i]];
732 if (x < element.xmin || x > element.xmax ||
733 y < element.ymin || y > element.ymax) continue;
734 if (!CheckElement(x, y, element, w)) continue;
735 const unsigned int nVertices = element.type + 1;
736 for (unsigned int j = 0; j < nVertices; ++j) {
737 const Vertex& vj = m_vertices[element.vertex[j]];
738 emob += w[j] * vj.emob;
739 hmob += w[j] * vj.hmob;
740 }
741 m_lastElement = last.neighbours[i];
742 return true;
743 }
744 }
745
746 // The point is not in the previous element nor in the adjacent ones.
747 // We have to loop over all elements.
748 const unsigned int nElements = m_elements.size();
749 for (unsigned int i = 0; i < nElements; ++i) {
750 const Element& element = m_elements[i];
751 if (x < element.xmin || x > element.xmax ||
752 y < element.ymin || y > element.ymax) continue;
753 if (!CheckElement(x, y, element, w)) continue;
754 const unsigned int nVertices = element.type + 1;
755 for (unsigned int j = 0; j < nVertices; ++j) {
756 const Vertex& vj = m_vertices[element.vertex[j]];
757 emob += w[j] * vj.emob;
758 hmob += w[j] * vj.hmob;
759 }
760 m_lastElement = i;
761 return true;
762 }
763
764 // Point is outside the mesh.
765 if (m_debug) {
766 std::cerr << m_className << "::GetMobility:\n"
767 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
768 }
769 return false;
770}

◆ GetNode()

bool Garfield::ComponentTcad2d::GetNode ( const unsigned int  i,
double &  x,
double &  y,
double &  v,
double &  ex,
double &  ey 
) const

Definition at line 1376 of file ComponentTcad2d.cc.

1378 {
1379
1380 if (i >= m_vertices.size()) {
1381 std::cerr << m_className << "::GetNode:\n"
1382 << " Node index (" << i << ") out of range.\n";
1383 return false;
1384 }
1385
1386 x = m_vertices[i].x;
1387 y = m_vertices[i].y;
1388 v = m_vertices[i].p;
1389 ex = m_vertices[i].ex;
1390 ey = m_vertices[i].ey;
1391 return true;
1392}

◆ GetNumberOfAcceptors()

int Garfield::ComponentTcad2d::GetNumberOfAcceptors ( )
inline

Definition at line 86 of file ComponentTcad2d.hh.

86{ return m_acceptors.size(); }

◆ GetNumberOfDonors()

int Garfield::ComponentTcad2d::GetNumberOfDonors ( )
inline

Definition at line 85 of file ComponentTcad2d.hh.

85{ return m_donors.size(); }

◆ GetNumberOfElements()

unsigned int Garfield::ComponentTcad2d::GetNumberOfElements ( ) const
inline

Definition at line 56 of file ComponentTcad2d.hh.

56{ return m_elements.size(); }

◆ GetNumberOfNodes()

unsigned int Garfield::ComponentTcad2d::GetNumberOfNodes ( ) const
inline

Definition at line 63 of file ComponentTcad2d.hh.

63{ return m_vertices.size(); }

◆ GetNumberOfRegions()

unsigned int Garfield::ComponentTcad2d::GetNumberOfRegions ( ) const
inline

Definition at line 47 of file ComponentTcad2d.hh.

47{ return m_regions.size(); }

◆ GetRegion()

void Garfield::ComponentTcad2d::GetRegion ( const unsigned int  i,
std::string &  name,
bool &  active 
) const

Definition at line 1257 of file ComponentTcad2d.cc.

1258 {
1259
1260 if (i >= m_regions.size()) {
1261 std::cerr << m_className << "::GetRegion:\n"
1262 << " Region " << i << " does not exist.\n";
1263 return;
1264 }
1265 name = m_regions[i].name;
1266 active = m_regions[i].drift;
1267}

◆ GetVoltageRange()

bool Garfield::ComponentTcad2d::GetVoltageRange ( double &  vmin,
double &  vmax 
)
virtual

Calculate the voltage range [V].

Implements Garfield::ComponentBase.

Definition at line 1215 of file ComponentTcad2d.cc.

1215 {
1216
1217 if (!m_ready) return false;
1218 vmin = m_pMin;
1219 vmax = m_pMax;
1220 return true;
1221}

◆ HoleAttachment()

bool Garfield::ComponentTcad2d::HoleAttachment ( const double  ,
const double  ,
const double  ,
double &  eta 
)
virtual

Get the hole attachment coefficient.

Reimplemented from Garfield::ComponentBase.

Definition at line 113 of file ComponentTcad2d.cc.

114 {
115
116 eta = 0.;
117 if (!m_validTraps) {
118 std::cerr << m_className << "::HoleAttachment:\n"
119 << " Trap cross-sections or concentrations are invalid.\n";
120 return false;
121 }
122
123 if (m_donors.empty() && m_acceptors.empty()) {
124 if (m_debug) {
125 std::cerr << m_className << "::HoleAttachment:\n"
126 << " There are no traps defined.\n";
127 }
128 return true;
129 }
130
131 const unsigned int nAcceptors = m_acceptors.size();
132 for (unsigned int i = 0; i < nAcceptors; ++i) {
133 const Defect& acceptor = m_acceptors[i];
134 double f = 0.;
135 GetAcceptorOccupation(x, y, z, i, f);
136 eta += acceptor.conc * acceptor.xsech * f;
137 }
138 const unsigned int nDonors = m_donors.size();
139 for (unsigned int i = 0; i < nDonors; ++i) {
140 const Defect& donor = m_donors[i];
141 double f = 0.;
142 GetDonorOccupation(x, y, z, i, f);
143 eta += donor.conc * donor.xsech * (1. - f);
144 }
145 return true;
146}

◆ HoleVelocity()

void Garfield::ComponentTcad2d::HoleVelocity ( const double  ,
const double  ,
const double  ,
double &  vx,
double &  vy,
double &  vz,
Medium *&  ,
int &  status 
)
virtual

Get the hole drift velocity.

Reimplemented from Garfield::ComponentBase.

Definition at line 366 of file ComponentTcad2d.cc.

369 {
370
371 // Initialise.
372 vx = vy = vz = 0.;
373 m = NULL;
374
375 // Make sure the field map has been loaded.
376 if (!m_ready) {
377 std::cerr << m_className << "::HoleVelocity:\n"
378 << " Field map is not available for interpolation.\n";
379 status = -10;
380 return;
381 }
382
383 double x = xin, y = yin, z = zin;
384 // In case of periodicity, reduce to the cell volume.
385 bool xmirr = false, ymirr = false;
386 MapCoordinates(x, y, xmirr, ymirr);
387 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB) {
388 status = -11;
389 return;
390 }
391 if (m_hasRangeZ && (z < m_zMinBB || z > m_zMaxBB)) {
392 status = -11;
393 return;
394 }
395
396 // Assume this will work.
397 status = 0;
398
399 double w[nMaxVertices] = {0};
400 if (m_lastElement >= 0) {
401 // Check if the point is still located in the previously found element.
402 const Element& last = m_elements[m_lastElement];
403 if (x >= last.xmin && x <= last.xmax && y >= last.ymin && y <= last.ymax) {
404 if (CheckElement(x, y, last, w)) {
405 const unsigned int nVertices = last.type + 1;
406 for (unsigned int j = 0; j < nVertices; ++j) {
407 const Vertex& vj = m_vertices[last.vertex[j]];
408 vx += w[j] * vj.hVx;
409 vy += w[j] * vj.hVy;
410 }
411 if (xmirr) vx = -vx;
412 if (ymirr) vy = -vy;
413 m = m_regions[last.region].medium;
414 if (!m_regions[last.region].drift || !m) status = -5;
415 return;
416 }
417 }
418 // The point is not in the previous element.
419 // Check the adjacent elements.
420 const unsigned int nNeighbours = last.neighbours.size();
421 for (unsigned int i = 0; i < nNeighbours; ++i) {
422 const Element& element = m_elements[last.neighbours[i]];
423 if (x < element.xmin || x > element.xmax ||
424 y < element.ymin || y > element.ymax) continue;
425 if (!CheckElement(x, y, element, w)) continue;
426 const unsigned int nVertices = element.type + 1;
427 for (unsigned int j = 0; j < nVertices; ++j) {
428 const Vertex& vj = m_vertices[element.vertex[j]];
429 vx += w[j] * vj.hVx;
430 vy += w[j] * vj.hVy;
431 }
432 if (xmirr) vx = -vx;
433 if (ymirr) vy = -vy;
434 m = m_regions[element.region].medium;
435 if (!m_regions[element.region].drift || !m) status = -5;
436 m_lastElement = last.neighbours[i];
437 return;
438 }
439 }
440
441 // The point is not in the previous element nor in the adjacent ones.
442 // We have to loop over all elements.
443 const unsigned int nElements = m_elements.size();
444 for (unsigned int i = 0; i < nElements; ++i) {
445 const Element& element = m_elements[i];
446 if (x < element.xmin || x > element.xmax ||
447 y < element.ymin || y > element.ymax) continue;
448 if (!CheckElement(x, y, element, w)) continue;
449 const unsigned int nVertices = element.type + 1;
450 for (unsigned int j = 0; j < nVertices; ++j) {
451 const Vertex& vj = m_vertices[element.vertex[j]];
452 vx += w[j] * vj.hVx;
453 vy += w[j] * vj.hVy;
454 }
455 if (xmirr) vx = -vx;
456 if (ymirr) vy = -vy;
457 m = m_regions[element.region].medium;
458 if (!m_regions[element.region].drift || !m) status = -5;
459 m_lastElement = i;
460 return;
461 }
462
463 // Point is outside the mesh.
464 if (m_debug) {
465 std::cerr << m_className << "::HoleVelocity:\n"
466 << " Point (" << x << ", " << y << ") is outside the mesh.\n";
467 }
468 status = -6;
469}

◆ Initialise()

bool Garfield::ComponentTcad2d::Initialise ( const std::string &  gridfilename,
const std::string &  datafilename 
)

Definition at line 947 of file ComponentTcad2d.cc.

948 {
949
950 m_ready = false;
951
952 m_hasPotential = m_hasField = false;
953 m_hasElectronMobility = m_hasHoleMobility = false;
954 m_validTraps = false;
955 m_donors.clear();
956 m_acceptors.clear();
957
958 // Import mesh data from .grd file.
959 if (!LoadGrid(gridfilename)) {
960 std::cerr << m_className << "::Initialise:\n"
961 << " Importing mesh data failed.\n";
962 return false;
963 }
964
965 // Import electric field, potential, mobilities and
966 // trap occupation values from .dat file.
967 if (!LoadData(datafilename)) {
968 std::cerr << m_className << "::Initialise:\n"
969 << " Importing electric field and potential failed.\n";
970 return false;
971 }
972
973 // Find min./max. coordinates and potentials.
974 m_xMaxBB = m_xMinBB = m_vertices[m_elements[0].vertex[0]].x;
975 m_yMaxBB = m_yMinBB = m_vertices[m_elements[0].vertex[0]].y;
976 m_pMax = m_pMin = m_vertices[m_elements[0].vertex[0]].p;
977 const unsigned int nElements = m_elements.size();
978 for (unsigned int i = 0; i < nElements; ++i) {
979 const Vertex& v0 = m_vertices[m_elements[i].vertex[0]];
980 const Vertex& v1 = m_vertices[m_elements[i].vertex[1]];
981 double xmin = std::min(v0.x, v1.x);
982 double xmax = std::max(v0.x, v1.x);
983 double ymin = std::min(v0.y, v1.y);
984 double ymax = std::max(v0.y, v1.y);
985 m_pMin = std::min(m_pMin, std::min(v0.p, v1.p));
986 m_pMax = std::max(m_pMax, std::max(v0.p, v1.p));
987 if (m_elements[i].type > 1) {
988 const Vertex& v2 = m_vertices[m_elements[i].vertex[2]];
989 xmin = std::min(xmin, v2.x);
990 xmax = std::max(xmax, v2.x);
991 ymin = std::min(ymin, v2.y);
992 ymax = std::max(ymax, v2.y);
993 m_pMin = std::min(m_pMin, v2.p);
994 m_pMax = std::max(m_pMax, v2.p);
995 }
996 if (m_elements[i].type > 2) {
997 const Vertex& v3 = m_vertices[m_elements[i].vertex[3]];
998 xmin = std::min(xmin, v3.x);
999 xmax = std::max(xmax, v3.x);
1000 ymin = std::min(ymin, v3.y);
1001 ymax = std::max(ymax, v3.y);
1002 m_pMin = std::min(m_pMin, v3.p);
1003 m_pMax = std::max(m_pMax, v3.p);
1004 }
1005 const double tol = 1.e-6;
1006 m_elements[i].xmin = xmin - tol;
1007 m_elements[i].xmax = xmax + tol;
1008 m_elements[i].ymin = ymin - tol;
1009 m_elements[i].ymax = ymax + tol;
1010 m_xMinBB = std::min(m_xMinBB, xmin);
1011 m_xMaxBB = std::max(m_xMaxBB, xmax);
1012 m_yMinBB = std::min(m_yMinBB, ymin);
1013 m_yMaxBB = std::max(m_yMaxBB, ymax);
1014 }
1015
1016 std::cout << m_className << "::Initialise:\n"
1017 << " Available data:\n";
1018 if (m_hasPotential) {
1019 std::cout << " Electrostatic potential\n";
1020 }
1021 if (m_hasField) {
1022 std::cout << " Electric field\n";
1023 }
1024 if (m_hasElectronMobility) {
1025 std::cout << " Electron mobility\n";
1026 }
1027 if (m_hasHoleMobility) {
1028 std::cout << " Hole mobility\n";
1029 }
1030 if (m_hasElectronVelocity) {
1031 std::cout << " Electron velocity\n";
1032 }
1033 if (m_hasHoleVelocity) {
1034 std::cout << " Hole velocity\n";
1035 }
1036 if (m_hasElectronLifetime) {
1037 std::cout << " Electron lifetimes\n";
1038 }
1039 if (m_hasHoleLifetime) {
1040 std::cout << " Hole lifetimes\n";
1041 }
1042 if (!m_donors.empty()) {
1043 std::cout << " " << m_donors.size() << " donor-type traps\n";
1044 }
1045 if (!m_acceptors.empty()) {
1046 std::cout << " " << m_acceptors.size() << " acceptor-type traps\n";
1047 }
1048 std::cout << " Bounding box:\n"
1049 << " " << m_xMinBB << " < x [cm] < " << m_xMaxBB << "\n"
1050 << " " << m_yMinBB << " < y [cm] < " << m_yMaxBB << "\n"
1051 << " Voltage range:\n"
1052 << " " << m_pMin << " < V < " << m_pMax << "\n";
1053
1054 bool ok = true;
1055
1056 // Count the number of elements belonging to a region.
1057 const int nRegions = m_regions.size();
1058 std::vector<int> nElementsRegion(nRegions, 0);
1059
1060 // Count the different element shapes.
1061 unsigned int nLines = 0;
1062 unsigned int nTriangles = 0;
1063 unsigned int nRectangles = 0;
1064 unsigned int nOtherShapes = 0;
1065
1066 // Check if there are elements which are not part of any region.
1067 unsigned int nLoose = 0;
1068 std::vector<int> looseElements;
1069
1070 // Check if there are degenerate elements.
1071 unsigned int nDegenerate = 0;
1072 std::vector<int> degenerateElements;
1073
1074 for (unsigned int i = 0; i < nElements; ++i) {
1075 const Element& element = m_elements[i];
1076 if (element.type == 1) {
1077 ++nLines;
1078 if (element.vertex[0] == element.vertex[1]) {
1079 degenerateElements.push_back(i);
1080 ++nDegenerate;
1081 }
1082 } else if (element.type == 2) {
1083 ++nTriangles;
1084 if (element.vertex[0] == element.vertex[1] ||
1085 element.vertex[1] == element.vertex[2] ||
1086 element.vertex[2] == element.vertex[0]) {
1087 degenerateElements.push_back(i);
1088 ++nDegenerate;
1089 }
1090 } else if (element.type == 3) {
1091 ++nRectangles;
1092 if (element.vertex[0] == element.vertex[1] ||
1093 element.vertex[0] == element.vertex[2] ||
1094 element.vertex[0] == element.vertex[3] ||
1095 element.vertex[1] == element.vertex[2] ||
1096 element.vertex[1] == element.vertex[3] ||
1097 element.vertex[2] == element.vertex[3]) {
1098 degenerateElements.push_back(i);
1099 ++nDegenerate;
1100 }
1101 } else {
1102 // Other shapes should not occur, since they were excluded in LoadGrid.
1103 ++nOtherShapes;
1104 }
1105 if (element.region >= 0 && element.region < nRegions) {
1106 ++nElementsRegion[element.region];
1107 } else {
1108 looseElements.push_back(i);
1109 ++nLoose;
1110 }
1111 }
1112
1113 if (nDegenerate > 0) {
1114 std::cerr << m_className << "::Initialise:\n"
1115 << " The following elements are degenerate:\n";
1116 for (unsigned int i = 0; i < nDegenerate; ++i) {
1117 std::cerr << " " << degenerateElements[i] << "\n";
1118 }
1119 ok = false;
1120 }
1121
1122 if (nLoose > 0) {
1123 std::cerr << m_className << "::Initialise:\n"
1124 << " The following elements are not part of any region:\n";
1125 for (unsigned int i = 0; i < nLoose; ++i) {
1126 std::cerr << " " << looseElements[i] << "\n";
1127 }
1128 ok = false;
1129 }
1130
1131 std::cout << m_className << "::Initialise:\n"
1132 << " Number of regions: " << nRegions << "\n";
1133 for (int i = 0; i < nRegions; ++i) {
1134 std::cout << " " << i << ": " << m_regions[i].name << ", "
1135 << nElementsRegion[i] << " elements\n";
1136 }
1137
1138 std::cout << " Number of elements: " << nElements << "\n";
1139 if (nLines > 0) {
1140 std::cout << " " << nLines << " lines\n";
1141 }
1142 if (nTriangles > 0) {
1143 std::cout << " " << nTriangles << " triangles\n";
1144 }
1145 if (nRectangles > 0) {
1146 std::cout << " " << nRectangles << " rectangles\n";
1147 }
1148 if (nOtherShapes > 0) {
1149 std::cerr << " " << nOtherShapes << " elements of unknown type.\n"
1150 << " Program bug!\n";
1151 m_ready = false;
1152 Cleanup();
1153 return false;
1154 }
1155
1156 std::cout << " Number of vertices: " << m_vertices.size() << "\n";
1157
1158 // Find adjacent elements.
1159 std::cout << m_className << "::Initialise:\n"
1160 << " Looking for neighbouring elements. Be patient...\n";
1161 FindNeighbours();
1162
1163 if (!ok) {
1164 m_ready = false;
1165 Cleanup();
1166 return false;
1167 }
1168
1169 m_ready = true;
1170 UpdatePeriodicity();
1171 std::cout << m_className << "::Initialise:\n"
1172 << " Initialisation finished.\n";
1173 return true;
1174}

◆ PrintRegions()

void Garfield::ComponentTcad2d::PrintRegions ( ) const

Definition at line 1223 of file ComponentTcad2d.cc.

1223 {
1224
1225 // Do not proceed if not properly initialised.
1226 if (!m_ready) {
1227 std::cerr << m_className << "::PrintRegions:\n"
1228 << " Field map not yet initialised.\n";
1229 return;
1230 }
1231
1232 if (m_regions.empty()) {
1233 std::cerr << m_className << "::PrintRegions:\n"
1234 << " No regions are currently defined.\n";
1235 return;
1236 }
1237
1238 const unsigned int nRegions = m_regions.size();
1239 std::cout << m_className << "::PrintRegions:\n"
1240 << " Currently " << nRegions << " regions are defined.\n"
1241 << " Index Name Medium\n";
1242 for (unsigned int i = 0; i < nRegions; ++i) {
1243 std::cout << " " << i << " " << m_regions[i].name;
1244 if (!m_regions[i].medium) {
1245 std::cout << " none ";
1246 } else {
1247 std::cout << " " << m_regions[i].medium->GetName();
1248 }
1249 if (m_regions[i].drift) {
1250 std::cout << " (active region)\n";
1251 } else {
1252 std::cout << "\n";
1253 }
1254 }
1255}

◆ SetAcceptor()

bool Garfield::ComponentTcad2d::SetAcceptor ( const unsigned int  acceptorNumber,
const double  eXsec,
const double  hxSec,
const double  concentration 
)

Definition at line 62 of file ComponentTcad2d.cc.

64 {
65
66 if (acceptorNumber >= m_acceptors.size()) {
67 std::cerr << m_className << "::SetAcceptor:\n"
68 << " Index (" << acceptorNumber << ") out of range.\n";
69 return false;
70 }
71 m_acceptors[acceptorNumber].xsece = eXsec;
72 m_acceptors[acceptorNumber].xsech = hXsec;
73 m_acceptors[acceptorNumber].conc = conc;
74
75 m_validTraps = CheckTraps();
76 return true;
77}

◆ SetDonor()

bool Garfield::ComponentTcad2d::SetDonor ( const unsigned int  donorNumber,
const double  eXsec,
const double  hxSec,
const double  concentration 
)

Definition at line 44 of file ComponentTcad2d.cc.

46 {
47
48
49 if (donorNumber >= m_donors.size()) {
50 std::cerr << m_className << "::SetDonor:\n"
51 << " Index (" << donorNumber << ") out of range.\n";
52 return false;
53 }
54 m_donors[donorNumber].xsece = eXsec;
55 m_donors[donorNumber].xsech = hXsec;
56 m_donors[donorNumber].conc = conc;
57
58 m_validTraps = CheckTraps();
59 return true;
60}

◆ SetDriftRegion()

void Garfield::ComponentTcad2d::SetDriftRegion ( const unsigned int  ireg)

Definition at line 1269 of file ComponentTcad2d.cc.

1269 {
1270
1271 if (i >= m_regions.size()) {
1272 std::cerr << m_className << "::SetDriftRegion:\n"
1273 << " Region " << i << " does not exist.\n";
1274 return;
1275 }
1276 m_regions[i].drift = true;
1277}

◆ SetMedium()

void Garfield::ComponentTcad2d::SetMedium ( const unsigned int  ireg,
Medium m 
)

Definition at line 1289 of file ComponentTcad2d.cc.

1289 {
1290
1291 if (i >= m_regions.size()) {
1292 std::cerr << m_className << "::SetMedium:\n"
1293 << " Region " << i << " does not exist.\n";
1294 return;
1295 }
1296
1297 if (!medium) {
1298 std::cerr << m_className << "::SetMedium:\n Null pointer.\n";
1299 return;
1300 }
1301
1302 m_regions[i].medium = medium;
1303}

◆ SetRangeZ()

void Garfield::ComponentTcad2d::SetRangeZ ( const double  zmin,
const double  zmax 
)

Definition at line 1203 of file ComponentTcad2d.cc.

1203 {
1204
1205 if (fabs(zmax - zmin) <= 0.) {
1206 std::cerr << m_className << "::SetRangeZ:\n"
1207 << " Zero range is not permitted.\n";
1208 return;
1209 }
1210 m_zMinBB = std::min(zmin, zmax);
1211 m_zMaxBB = std::max(zmin, zmax);
1212 m_hasRangeZ = true;
1213}

◆ UnsetDriftRegion()

void Garfield::ComponentTcad2d::UnsetDriftRegion ( const unsigned int  ireg)

Definition at line 1279 of file ComponentTcad2d.cc.

1279 {
1280
1281 if (i >= m_regions.size()) {
1282 std::cerr << m_className << "::UnsetDriftRegion:\n"
1283 << " Region " << i << " does not exist.\n";
1284 return;
1285 }
1286 m_regions[i].drift = false;
1287}

◆ WeightingField()

void Garfield::ComponentTcad2d::WeightingField ( const double  x,
const double  y,
const double  z,
double &  wx,
double &  wy,
double &  wz,
const std::string &  label 
)
virtual

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::ComponentBase.

Definition at line 148 of file ComponentTcad2d.cc.

150 {
151 int status = 0;
152 Medium* med = NULL;
153 double v = 0.;
154 ElectricField(x, y, z, wx, wy, wz, v, med, status);
155}

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