Garfield++ 3.0
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 ()
 Constructor.
 
 ~ComponentTcad2d ()
 Destructor.
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status) override
 Calculate the drift field [V/cm] and potential [V] at (x, y, z).
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status) override
 
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
 
MediumGetMedium (const double x, const double y, const double z) override
 Get the medium at a given location (x, y, z).
 
bool GetVoltageRange (double &vmin, double &vmax) override
 Calculate the voltage range [V].
 
bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
 Get the bounding box coordinates.
 
void SetRangeZ (const double zmin, const double zmax)
 
bool Initialise (const std::string &gridfilename, const std::string &datafilename)
 
bool SetWeightingField (const std::string &datfile1, const std::string &datfile2, const double dv)
 
void PrintRegions () const
 List all currently defined regions.
 
unsigned int GetNumberOfRegions () const
 Get the number of regions in the device.
 
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)
 Set the medium for a given region.
 
MediumGetMedium (const unsigned int ireg) const
 Get the medium for a given region.
 
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) override
 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) override
 Get the hole drift velocity.
 
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
 
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) 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.
 
- 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
 Calculate the drift field [V/cm] and potential [V] at (x, y, z).
 
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 DelayedWeightingField (const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, 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.
 
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 IntegrateFlux (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)
 
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, const bool centre, double &rc)
 
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
 Reset the component.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 
- Protected Attributes inherited from Garfield::ComponentBase
std::string m_className = "ComponentBase"
 Class name.
 
GeometryBasem_geometry = nullptr
 Pointer to the geometry.
 
bool m_ready = false
 Ready for use?
 
bool m_activeTraps = false
 Does the component have traps?
 
bool m_hasVelocityMap = false
 Does the component have velocity maps?
 
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.
 
double m_bx0 = 0.
 
double m_by0 = 0.
 
double m_bz0 = 0.
 
bool m_debug = false
 Switch on/off debugging messages.
 

Detailed Description

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

Definition at line 12 of file ComponentTcad2d.hh.

Constructor & Destructor Documentation

◆ ComponentTcad2d()

Garfield::ComponentTcad2d::ComponentTcad2d ( )

Constructor.

Definition at line 14 of file ComponentTcad2d.cc.

14 : ComponentBase() {
15 m_className = "ComponentTcad2d";
16
17 m_regions.reserve(10);
18 m_vertices.reserve(10000);
19 m_elements.reserve(10000);
20}
ComponentBase()
Constructor.
Definition: ComponentBase.cc:9
std::string m_className
Class name.

◆ ~ComponentTcad2d()

Garfield::ComponentTcad2d::~ComponentTcad2d ( )
inline

Destructor.

Definition at line 17 of file ComponentTcad2d.hh.

17{}

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 
)
overridevirtual

Calculate the drift field [V/cm] and potential [V] at (x, y, z).

Implements Garfield::ComponentBase.

Definition at line 176 of file ComponentTcad2d.cc.

179 {
180 // Assume this will work.
181 status = 0;
182 // Initialise.
183 ex = ey = ez = p = 0.;
184 m = nullptr;
185
186 // Make sure the field map has been loaded.
187 if (!m_ready) {
188 std::cerr << m_className << "::ElectricField:\n"
189 << " Field map is not available for interpolation.\n";
190 status = -10;
191 return;
192 }
193
194 // In case of periodicity, reduce to the cell volume.
195 double x = xin, y = yin, z = zin;
196 bool xmirr = false, ymirr = false;
197 MapCoordinates(x, y, xmirr, ymirr);
198 // Check if the point is inside the bounding box.
199 if (!InsideBoundingBox(x, y, z)) {
200 status = -6;
201 return;
202 }
203
204 std::array<double, nMaxVertices> w;
205 const unsigned int i = FindElement(x, y, w);
206 if (i >= m_elements.size()) {
207 // Point is outside the mesh.
208 status = -6;
209 return;
210 }
211
212 const Element& element = m_elements[i];
213 const unsigned int nVertices = element.type + 1;
214 for (unsigned int j = 0; j < nVertices; ++j) {
215 const Vertex& vj = m_vertices[element.vertex[j]];
216 ex += w[j] * vj.ex;
217 ey += w[j] * vj.ey;
218 p += w[j] * vj.p;
219 }
220 if (xmirr) ex = -ex;
221 if (ymirr) ey = -ey;
222 m = m_regions[element.region].medium;
223 if (!m_regions[element.region].drift || !m) status = -5;
224 m_lastElement = i;
225}
bool m_ready
Ready for use?

Referenced by ElectricField().

◆ 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 
)
inlineoverridevirtual

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 23 of file ComponentTcad2d.hh.

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) override
Calculate the drift field [V/cm] and potential [V] at (x, y, z).

◆ ElectronAttachment()

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

Get the electron attachment coefficient.

Reimplemented from Garfield::ComponentBase.

Definition at line 52 of file ComponentTcad2d.cc.

53 {
54 eta = 0.;
55 if (!m_validTraps) {
56 std::cerr << m_className << "::ElectronAttachment:\n"
57 << " Trap cross-sections or concentrations are invalid.\n";
58 return false;
59 }
60
61 if (m_donors.empty() && m_acceptors.empty()) {
62 if (m_debug) {
63 std::cerr << m_className << "::ElectronAttachment: No traps defined.\n";
64 }
65 return true;
66 }
67
68 const unsigned int nAcceptors = m_acceptors.size();
69 for (unsigned int i = 0; i < nAcceptors; ++i) {
70 const Defect& acceptor = m_acceptors[i];
71 double f = 0.;
72 GetAcceptorOccupation(x, y, z, i, f);
73 eta += acceptor.conc * acceptor.xsece * (1. - f);
74 }
75 const unsigned int nDonors = m_donors.size();
76 for (unsigned int i = 0; i < nDonors; ++i) {
77 const Defect& donor = m_donors[i];
78 double f = 0.;
79 GetDonorOccupation(x, y, z, i, f);
80 eta += donor.conc * donor.xsece * f;
81 }
82 return true;
83}
bool m_debug
Switch on/off debugging messages.
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 
)
overridevirtual

Get the electron drift velocity.

Reimplemented from Garfield::ComponentBase.

Definition at line 227 of file ComponentTcad2d.cc.

229 {
230 // Assume this will work.
231 status = 0;
232 // Initialise.
233 vx = vy = vz = 0.;
234 m = nullptr;
235 // Make sure the field map has been loaded.
236 if (!m_ready) {
237 std::cerr << m_className << "::ElectronVelocity:\n"
238 << " Field map is not available for interpolation.\n";
239 status = -10;
240 return;
241 }
242
243 double x = xin, y = yin, z = zin;
244 // In case of periodicity, reduce to the cell volume.
245 bool xmirr = false, ymirr = false;
246 MapCoordinates(x, y, xmirr, ymirr);
247 if (!InsideBoundingBox(x, y, z)) {
248 status = -6;
249 return;
250 }
251
252 std::array<double, nMaxVertices> w;
253 const unsigned int i = FindElement(x, y, w);
254 if (i >= m_elements.size()) {
255 // Point is outside the mesh.
256 status = -6;
257 return;
258 }
259
260 const Element& element = m_elements[i];
261 const unsigned int nVertices = element.type + 1;
262 for (unsigned int j = 0; j < nVertices; ++j) {
263 const Vertex& vj = m_vertices[element.vertex[j]];
264 vx += w[j] * vj.eVx;
265 vy += w[j] * vj.eVy;
266 }
267 if (xmirr) vx = -vx;
268 if (ymirr) vy = -vy;
269 m = m_regions[element.region].medium;
270 if (!m_regions[element.region].drift || !m) status = -5;
271 m_lastElement = i;
272}

◆ GetAcceptorOccupation()

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

Definition at line 497 of file ComponentTcad2d.cc.

500 {
501 f = 0.;
502 if (acceptorNumber >= m_acceptors.size()) {
503 std::cerr << m_className << "::GetAcceptorOccupation:\n"
504 << " Acceptor " << acceptorNumber << " does not exist.\n";
505 return false;
506 }
507
508 // Make sure the field map has been loaded.
509 if (!m_ready) {
510 std::cerr << m_className << "::GetAcceptorOccupation:\n"
511 << " Field map is not available for interpolation.\n";
512 return false;
513 }
514
515 double x = xin, y = yin, z = zin;
516 // In case of periodicity, reduce to the cell volume.
517 bool xmirr = false, ymirr = false;
518 MapCoordinates(x, y, xmirr, ymirr);
519 // Check if the point is inside the bounding box.
520 if (!InsideBoundingBox(x, y, z)) return false;
521
522 std::array<double, nMaxVertices> w;
523 const unsigned int i = FindElement(x, y, w);
524 if (i >= m_elements.size()) {
525 // Point is outside the mesh.
526 return false;
527 }
528
529 const Element& element = m_elements[i];
530 const unsigned int nVertices = element.type + 1;
531 for (unsigned int j = 0; j < nVertices; ++j) {
532 const Vertex& vj = m_vertices[element.vertex[j]];
533 f += w[j] * vj.acceptorOcc[acceptorNumber];
534 }
535 m_lastElement = i;
536 return true;
537}

Referenced by ElectronAttachment(), and HoleAttachment().

◆ GetBoundingBox()

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

Get the bounding box coordinates.

Reimplemented from Garfield::ComponentBase.

Definition at line 832 of file ComponentTcad2d.cc.

833 {
834 if (!m_ready) return false;
835 if (m_periodic[0] || m_mirrorPeriodic[0]) {
836 xmin = -INFINITY;
837 xmax = +INFINITY;
838 } else {
839 xmin = m_xMinBB;
840 xmax = m_xMaxBB;
841 }
842
843 if (m_periodic[1] || m_mirrorPeriodic[1]) {
844 ymin = -INFINITY;
845 ymax = +INFINITY;
846 } else {
847 ymin = m_yMinBB;
848 ymax = m_yMaxBB;
849 }
850
851 if (m_hasRangeZ) {
852 zmin = m_zMinBB;
853 zmax = m_zMaxBB;
854 }
855 return true;
856}
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.

◆ GetDonorOccupation()

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

Definition at line 455 of file ComponentTcad2d.cc.

458 {
459 f = 0.;
460 if (donorNumber >= m_donors.size()) {
461 std::cerr << m_className << "::GetDonorOccupation:\n"
462 << " Donor " << donorNumber << " does not exist.\n";
463 return false;
464 }
465
466 // Make sure the field map has been loaded.
467 if (!m_ready) {
468 std::cerr << m_className << "::GetDonorOccupation:\n"
469 << " Field map is not available for interpolation.\n";
470 return false;
471 }
472
473 double x = xin, y = yin, z = zin;
474 // In case of periodicity, reduce to the cell volume.
475 bool xmirr = false, ymirr = false;
476 MapCoordinates(x, y, xmirr, ymirr);
477 // Check if the point is inside the bounding box.
478 if (!InsideBoundingBox(x, y, z)) return false;
479
480 std::array<double, nMaxVertices> w;
481 const unsigned int i = FindElement(x, y, w);
482 if (i >= m_elements.size()) {
483 // Point is outside the mesh.
484 return false;
485 }
486
487 const Element& element = m_elements[i];
488 const unsigned int nVertices = element.type + 1;
489 for (unsigned int j = 0; j < nVertices; ++j) {
490 const Vertex& vj = m_vertices[element.vertex[j]];
491 f += w[j] * vj.donorOcc[donorNumber];
492 }
493 m_lastElement = i;
494 return true;
495}

Referenced by ElectronAttachment(), and HoleAttachment().

◆ GetElectronLifetime()

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

Reimplemented from Garfield::ComponentBase.

Definition at line 351 of file ComponentTcad2d.cc.

352 {
353 tau = 0.;
354 // Make sure the field map has been loaded.
355 if (!m_ready) {
356 std::cerr << m_className << "::GetElectronLifetime:\n"
357 << " Field map is not available for interpolation.\n";
358 return false;
359 }
360
361 double x = xin, y = yin, z = zin;
362 // In case of periodicity, reduce to the cell volume.
363 bool xmirr = false, ymirr = false;
364 MapCoordinates(x, y, xmirr, ymirr);
365 // Check if the point is inside the bounding box.
366 if (!InsideBoundingBox(x, y, z)) return false;
367
368 std::array<double, nMaxVertices> w;
369 const unsigned int i = FindElement(x, y, w);
370 if (i >= m_elements.size()) {
371 // Point is outside the mesh.
372 return false;
373 }
374
375 const Element& element = m_elements[i];
376 const unsigned int nVertices = element.type + 1;
377 for (unsigned int j = 0; j < nVertices; ++j) {
378 const Vertex& vj = m_vertices[element.vertex[j]];
379 tau += w[j] * vj.eTau;
380 }
381 m_lastElement = i;
382 return true;
383}

◆ GetElement() [1/2]

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

Definition at line 957 of file ComponentTcad2d.cc.

958 {
959 if (i >= m_elements.size()) {
960 std::cerr << m_className << "::GetElement: Index out of range.\n";
961 return false;
962 }
963
964 const Element& element = m_elements[i];
965 if (element.type == 1) {
966 const Vertex& v0 = m_vertices[element.vertex[0]];
967 const Vertex& v1 = m_vertices[element.vertex[1]];
968 const double dx = v1.x - v0.x;
969 const double dy = v1.y - v0.y;
970 const double d = sqrt(dx * dx + dy * dy);
971 dmin = dmax = vol = d;
972 } else if (m_elements[i].type == 2) {
973 const Vertex& v0 = m_vertices[element.vertex[0]];
974 const Vertex& v1 = m_vertices[element.vertex[1]];
975 const Vertex& v2 = m_vertices[element.vertex[2]];
976 vol = 0.5 *
977 fabs((v2.x - v0.x) * (v1.y - v0.y) - (v2.y - v0.y) * (v1.x - v0.x));
978 const double a = sqrt(pow(v1.x - v0.x, 2) + pow(v1.y - v0.y, 2));
979 const double b = sqrt(pow(v2.x - v0.x, 2) + pow(v2.y - v0.y, 2));
980 const double c = sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2));
981 dmin = std::min(std::min(a, b), c);
982 dmax = std::max(std::max(a, b), c);
983 } else if (m_elements[i].type == 3) {
984 const Vertex& v0 = m_vertices[element.vertex[0]];
985 const Vertex& v1 = m_vertices[element.vertex[1]];
986 const Vertex& v3 = m_vertices[element.vertex[3]];
987 const double a = sqrt(pow(v1.x - v0.x, 2) + pow(v1.y - v0.y, 2));
988 const double b = sqrt(pow(v3.x - v0.x, 2) + pow(v3.y - v0.y, 2));
989 vol = a * b;
990 dmin = std::min(a, b);
991 dmax = sqrt(a * a + b * b);
992 } else {
993 std::cerr << m_className << "::GetElement:\n"
994 << " Unexpected element type (" << type << ")\n";
995 return false;
996 }
997 return true;
998}
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 1000 of file ComponentTcad2d.cc.

1003 {
1004 if (!GetElement(i, vol, dmin, dmax, type)) return false;
1005 const Element& element = m_elements[i];
1006 node1 = element.vertex[0];
1007 node2 = element.vertex[1];
1008 node3 = element.vertex[2];
1009 node4 = element.vertex[3];
1010 reg = element.region;
1011 return true;
1012}
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 
)
overridevirtual

Reimplemented from Garfield::ComponentBase.

Definition at line 384 of file ComponentTcad2d.cc.

385 {
386 tau = 0.;
387 // Make sure the field map has been loaded.
388 if (!m_ready) {
389 std::cerr << m_className << "::GetHoleLifetime:\n"
390 << " Field map is not available for interpolation.\n";
391 return false;
392 }
393
394 double x = xin, y = yin, z = zin;
395 // In case of periodicity, reduce to the cell volume.
396 bool xmirr = false, ymirr = false;
397 MapCoordinates(x, y, xmirr, ymirr);
398 // Check if the point is inside the bounding box.
399 if (!InsideBoundingBox(x, y, z)) return false;
400
401 std::array<double, nMaxVertices> w;
402 const unsigned int i = FindElement(x, y, w);
403 if (i >= m_elements.size()) {
404 // Point is outside the mesh.
405 return false;
406 }
407
408 const Element& element = m_elements[i];
409 const unsigned int nVertices = element.type + 1;
410 for (unsigned int j = 0; j < nVertices; ++j) {
411 const Vertex& vj = m_vertices[element.vertex[j]];
412 tau += w[j] * vj.hTau;
413 }
414 m_lastElement = i;
415 return true;
416}

◆ GetMedium() [1/2]

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

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

Reimplemented from Garfield::ComponentBase.

Definition at line 323 of file ComponentTcad2d.cc.

324 {
325 // Make sure the field map has been loaded.
326 if (!m_ready) {
327 std::cerr << m_className << "::GetMedium:\n"
328 << " Field map not available for interpolation.\n";
329 return nullptr;
330 }
331
332 double x = xin, y = yin, z = zin;
333 // In case of periodicity, reduce to the cell volume.
334 bool xmirr = false, ymirr = false;
335 MapCoordinates(x, y, xmirr, ymirr);
336 // Check if the point is inside the bounding box.
337 if (!InsideBoundingBox(x, y, z)) return nullptr;
338
339 // Shape functions
340 std::array<double, nMaxVertices> w;
341 const unsigned int i = FindElement(x, y, w);
342 if (i >= m_elements.size()) {
343 // Point is outside the mesh.
344 return nullptr;
345 }
346 m_lastElement = i;
347 const Element& element = m_elements[i];
348 return m_regions[element.region].medium;
349}

◆ GetMedium() [2/2]

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

Get the medium for a given region.

Definition at line 948 of file ComponentTcad2d.cc.

948 {
949 if (i >= m_regions.size()) {
950 std::cerr << m_className << "::GetMedium: Index out of range.\n";
951 return nullptr;
952 }
953
954 return m_regions[i].medium;
955}

◆ GetMobility()

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

Definition at line 418 of file ComponentTcad2d.cc.

420 {
421 emob = hmob = 0.;
422
423 // Make sure the field map has been loaded.
424 if (!m_ready) {
425 std::cerr << m_className << "::GetMobility:\n"
426 << " Field map is not available for interpolation.\n";
427 return false;
428 }
429
430 double x = xin, y = yin, z = zin;
431 // In case of periodicity, reduce to the cell volume.
432 bool xmirr = false, ymirr = false;
433 MapCoordinates(x, y, xmirr, ymirr);
434 // Check if the point is inside the bounding box.
435 if (!InsideBoundingBox(x, y, z)) return false;
436
437 std::array<double, nMaxVertices> w;
438 const unsigned int i = FindElement(x, y, w);
439 if (i >= m_elements.size()) {
440 // Point is outside the mesh.
441 return false;
442 }
443
444 const Element& element = m_elements[i];
445 const unsigned int nVertices = element.type + 1;
446 for (unsigned int j = 0; j < nVertices; ++j) {
447 const Vertex& vj = m_vertices[element.vertex[j]];
448 emob += w[j] * vj.emob;
449 hmob += w[j] * vj.hmob;
450 }
451 m_lastElement = i;
452 return true;
453}

◆ GetNode()

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

Definition at line 1014 of file ComponentTcad2d.cc.

1015 {
1016 if (i >= m_vertices.size()) {
1017 std::cerr << m_className << "::GetNode: Index out of range.\n";
1018 return false;
1019 }
1020
1021 x = m_vertices[i].x;
1022 y = m_vertices[i].y;
1023 v = m_vertices[i].p;
1024 ex = m_vertices[i].ex;
1025 ey = m_vertices[i].ey;
1026 return true;
1027}

◆ GetNumberOfAcceptors()

int Garfield::ComponentTcad2d::GetNumberOfAcceptors ( )
inline

Definition at line 102 of file ComponentTcad2d.hh.

102{ return m_acceptors.size(); }

◆ GetNumberOfDonors()

int Garfield::ComponentTcad2d::GetNumberOfDonors ( )
inline

Definition at line 101 of file ComponentTcad2d.hh.

101{ return m_donors.size(); }

◆ GetNumberOfElements()

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

Definition at line 74 of file ComponentTcad2d.hh.

74{ return m_elements.size(); }

◆ GetNumberOfNodes()

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

Definition at line 80 of file ComponentTcad2d.hh.

80{ return m_vertices.size(); }

◆ GetNumberOfRegions()

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

Get the number of regions in the device.

Definition at line 64 of file ComponentTcad2d.hh.

64{ return m_regions.size(); }

◆ GetRegion()

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

Definition at line 908 of file ComponentTcad2d.cc.

909 {
910 if (i >= m_regions.size()) {
911 std::cerr << m_className << "::GetRegion: Index out of range.\n";
912 return;
913 }
914 name = m_regions[i].name;
915 active = m_regions[i].drift;
916}

◆ GetVoltageRange()

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

Calculate the voltage range [V].

Implements Garfield::ComponentBase.

Definition at line 868 of file ComponentTcad2d.cc.

868 {
869 if (!m_ready) return false;
870 vmin = m_pMin;
871 vmax = m_pMax;
872 return true;
873}

◆ HoleAttachment()

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

Get the hole attachment coefficient.

Reimplemented from Garfield::ComponentBase.

Definition at line 85 of file ComponentTcad2d.cc.

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

◆ HoleVelocity()

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

Get the hole drift velocity.

Reimplemented from Garfield::ComponentBase.

Definition at line 274 of file ComponentTcad2d.cc.

276 {
277
278 // Assume this will work.
279 status = 0;
280 // Initialise.
281 vx = vy = vz = 0.;
282 m = nullptr;
283
284 // Make sure the field map has been loaded.
285 if (!m_ready) {
286 std::cerr << m_className << "::HoleVelocity:\n"
287 << " Field map is not available for interpolation.\n";
288 status = -10;
289 return;
290 }
291
292 double x = xin, y = yin, z = zin;
293 // In case of periodicity, reduce to the cell volume.
294 bool xmirr = false, ymirr = false;
295 MapCoordinates(x, y, xmirr, ymirr);
296 if (!InsideBoundingBox(x, y, z)) {
297 status = -6;
298 return;
299 }
300
301 std::array<double, nMaxVertices> w;
302 const unsigned int i = FindElement(x, y, w);
303 if (i >= m_elements.size()) {
304 // Point is outside the mesh.
305 status = -6;
306 return;
307 }
308
309 const Element& element = m_elements[i];
310 const unsigned int nVertices = element.type + 1;
311 for (unsigned int j = 0; j < nVertices; ++j) {
312 const Vertex& vj = m_vertices[element.vertex[j]];
313 vx += w[j] * vj.hVx;
314 vy += w[j] * vj.hVy;
315 }
316 if (xmirr) vx = -vx;
317 if (ymirr) vy = -vy;
318 m = m_regions[element.region].medium;
319 if (!m_regions[element.region].drift || !m) status = -5;
320 m_lastElement = i;
321}

◆ Initialise()

bool Garfield::ComponentTcad2d::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 539 of file ComponentTcad2d.cc.

540 {
541 m_ready = false;
542
543 m_hasPotential = m_hasField = false;
544 m_hasElectronMobility = m_hasHoleMobility = false;
545 m_validTraps = false;
546 m_donors.clear();
547 m_acceptors.clear();
548
549 // Import mesh data from .grd file.
550 if (!LoadGrid(gridfilename)) {
551 std::cerr << m_className << "::Initialise:\n"
552 << " Importing mesh data failed.\n";
553 return false;
554 }
555
556 // Import electric field, potential, mobilities and
557 // trap occupation values from .dat file.
558 if (!LoadData(datafilename)) {
559 std::cerr << m_className << "::Initialise:\n"
560 << " Importing electric field and potential failed.\n";
561 return false;
562 }
563
564 // Find min./max. coordinates and potentials.
565 m_xMaxBB = m_xMinBB = m_vertices[m_elements[0].vertex[0]].x;
566 m_yMaxBB = m_yMinBB = m_vertices[m_elements[0].vertex[0]].y;
567 m_pMax = m_pMin = m_vertices[m_elements[0].vertex[0]].p;
568 for (auto& element : m_elements) {
569 const Vertex& v0 = m_vertices[element.vertex[0]];
570 const Vertex& v1 = m_vertices[element.vertex[1]];
571 double xmin = std::min(v0.x, v1.x);
572 double xmax = std::max(v0.x, v1.x);
573 double ymin = std::min(v0.y, v1.y);
574 double ymax = std::max(v0.y, v1.y);
575 m_pMin = std::min(m_pMin, std::min(v0.p, v1.p));
576 m_pMax = std::max(m_pMax, std::max(v0.p, v1.p));
577 if (element.type > 1) {
578 const Vertex& v2 = m_vertices[element.vertex[2]];
579 xmin = std::min(xmin, v2.x);
580 xmax = std::max(xmax, v2.x);
581 ymin = std::min(ymin, v2.y);
582 ymax = std::max(ymax, v2.y);
583 m_pMin = std::min(m_pMin, v2.p);
584 m_pMax = std::max(m_pMax, v2.p);
585 }
586 if (element.type > 2) {
587 const Vertex& v3 = m_vertices[element.vertex[3]];
588 xmin = std::min(xmin, v3.x);
589 xmax = std::max(xmax, v3.x);
590 ymin = std::min(ymin, v3.y);
591 ymax = std::max(ymax, v3.y);
592 m_pMin = std::min(m_pMin, v3.p);
593 m_pMax = std::max(m_pMax, v3.p);
594 }
595 constexpr double tol = 1.e-6;
596 element.xmin = xmin - tol;
597 element.xmax = xmax + tol;
598 element.ymin = ymin - tol;
599 element.ymax = ymax + tol;
600 m_xMinBB = std::min(m_xMinBB, xmin);
601 m_xMaxBB = std::max(m_xMaxBB, xmax);
602 m_yMinBB = std::min(m_yMinBB, ymin);
603 m_yMaxBB = std::max(m_yMaxBB, ymax);
604 }
605
606 std::cout << m_className << "::Initialise:\n"
607 << " Available data:\n";
608 if (m_hasPotential) {
609 std::cout << " Electrostatic potential\n";
610 }
611 if (m_hasField) {
612 std::cout << " Electric field\n";
613 }
614 if (m_hasElectronMobility) {
615 std::cout << " Electron mobility\n";
616 }
617 if (m_hasHoleMobility) {
618 std::cout << " Hole mobility\n";
619 }
620 if (m_hasElectronVelocity) {
621 std::cout << " Electron velocity\n";
622 }
623 if (m_hasHoleVelocity) {
624 std::cout << " Hole velocity\n";
625 }
626 if (m_hasElectronLifetime) {
627 std::cout << " Electron lifetimes\n";
628 }
629 if (m_hasHoleLifetime) {
630 std::cout << " Hole lifetimes\n";
631 }
632 if (!m_donors.empty()) {
633 std::cout << " " << m_donors.size() << " donor-type traps\n";
634 }
635 if (!m_acceptors.empty()) {
636 std::cout << " " << m_acceptors.size() << " acceptor-type traps\n";
637 }
638 std::cout << " Bounding box:\n"
639 << " " << m_xMinBB << " < x [cm] < " << m_xMaxBB << "\n"
640 << " " << m_yMinBB << " < y [cm] < " << m_yMaxBB << "\n"
641 << " Voltage range:\n"
642 << " " << m_pMin << " < V < " << m_pMax << "\n";
643
644 bool ok = true;
645
646 // Count the number of elements belonging to a region.
647 const int nRegions = m_regions.size();
648 std::vector<int> nElementsRegion(nRegions, 0);
649
650 // Count the different element shapes.
651 unsigned int nLines = 0;
652 unsigned int nTriangles = 0;
653 unsigned int nRectangles = 0;
654 unsigned int nOtherShapes = 0;
655
656 // Check if there are elements which are not part of any region.
657 unsigned int nLoose = 0;
658 std::vector<int> looseElements;
659
660 // Check if there are degenerate elements.
661 unsigned int nDegenerate = 0;
662 std::vector<int> degenerateElements;
663
664 const unsigned int nElements = m_elements.size();
665 for (unsigned int i = 0; i < nElements; ++i) {
666 const Element& element = m_elements[i];
667 if (element.type == 1) {
668 ++nLines;
669 if (element.vertex[0] == element.vertex[1]) {
670 degenerateElements.push_back(i);
671 ++nDegenerate;
672 }
673 } else if (element.type == 2) {
674 ++nTriangles;
675 if (element.vertex[0] == element.vertex[1] ||
676 element.vertex[1] == element.vertex[2] ||
677 element.vertex[2] == element.vertex[0]) {
678 degenerateElements.push_back(i);
679 ++nDegenerate;
680 }
681 } else if (element.type == 3) {
682 ++nRectangles;
683 if (element.vertex[0] == element.vertex[1] ||
684 element.vertex[0] == element.vertex[2] ||
685 element.vertex[0] == element.vertex[3] ||
686 element.vertex[1] == element.vertex[2] ||
687 element.vertex[1] == element.vertex[3] ||
688 element.vertex[2] == element.vertex[3]) {
689 degenerateElements.push_back(i);
690 ++nDegenerate;
691 }
692 } else {
693 // Other shapes should not occur, since they were excluded in LoadGrid.
694 ++nOtherShapes;
695 }
696 if (element.region >= 0 && element.region < nRegions) {
697 ++nElementsRegion[element.region];
698 } else {
699 looseElements.push_back(i);
700 ++nLoose;
701 }
702 }
703
704 if (nDegenerate > 0) {
705 std::cerr << m_className << "::Initialise:\n"
706 << " The following elements are degenerate:\n";
707 for (unsigned int i = 0; i < nDegenerate; ++i) {
708 std::cerr << " " << degenerateElements[i] << "\n";
709 }
710 ok = false;
711 }
712
713 if (nLoose > 0) {
714 std::cerr << m_className << "::Initialise:\n"
715 << " The following elements are not part of any region:\n";
716 for (unsigned int i = 0; i < nLoose; ++i) {
717 std::cerr << " " << looseElements[i] << "\n";
718 }
719 ok = false;
720 }
721
722 std::cout << m_className << "::Initialise:\n"
723 << " Number of regions: " << nRegions << "\n";
724 for (int i = 0; i < nRegions; ++i) {
725 std::cout << " " << i << ": " << m_regions[i].name << ", "
726 << nElementsRegion[i] << " elements\n";
727 }
728
729 std::cout << " Number of elements: " << nElements << "\n";
730 if (nLines > 0) {
731 std::cout << " " << nLines << " lines\n";
732 }
733 if (nTriangles > 0) {
734 std::cout << " " << nTriangles << " triangles\n";
735 }
736 if (nRectangles > 0) {
737 std::cout << " " << nRectangles << " rectangles\n";
738 }
739 if (nOtherShapes > 0) {
740 std::cerr << " " << nOtherShapes << " elements of unknown type.\n"
741 << " Program bug!\n";
742 m_ready = false;
743 Cleanup();
744 return false;
745 }
746
747 std::cout << " Number of vertices: " << m_vertices.size() << "\n";
748
749 // Find adjacent elements.
750 std::cout << m_className << "::Initialise:\n"
751 << " Looking for neighbouring elements. Be patient...\n";
752 FindNeighbours();
753
754 if (!ok) {
755 m_ready = false;
756 Cleanup();
757 return false;
758 }
759
760 m_ready = true;
761 UpdatePeriodicity();
762 std::cout << m_className << "::Initialise: Initialisation finished.\n";
763 return true;
764}

◆ PrintRegions()

void Garfield::ComponentTcad2d::PrintRegions ( ) const

List all currently defined regions.

Definition at line 875 of file ComponentTcad2d.cc.

875 {
876 // Do not proceed if not properly initialised.
877 if (!m_ready) {
878 std::cerr << m_className << "::PrintRegions:\n"
879 << " Field map not yet initialised.\n";
880 return;
881 }
882
883 if (m_regions.empty()) {
884 std::cerr << m_className << "::PrintRegions:\n"
885 << " No regions are currently defined.\n";
886 return;
887 }
888
889 const unsigned int nRegions = m_regions.size();
890 std::cout << m_className << "::PrintRegions:\n"
891 << " Currently " << nRegions << " regions are defined.\n"
892 << " Index Name Medium\n";
893 for (unsigned int i = 0; i < nRegions; ++i) {
894 std::cout << " " << i << " " << m_regions[i].name;
895 if (!m_regions[i].medium) {
896 std::cout << " none ";
897 } else {
898 std::cout << " " << m_regions[i].medium->GetName();
899 }
900 if (m_regions[i].drift) {
901 std::cout << " (active region)\n";
902 } else {
903 std::cout << "\n";
904 }
905 }
906}

◆ SetAcceptor()

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

Definition at line 37 of file ComponentTcad2d.cc.

39 {
40 if (acceptorNumber >= m_acceptors.size()) {
41 std::cerr << m_className << "::SetAcceptor: Index out of range.\n";
42 return false;
43 }
44 m_acceptors[acceptorNumber].xsece = eXsec;
45 m_acceptors[acceptorNumber].xsech = hXsec;
46 m_acceptors[acceptorNumber].conc = conc;
47
48 m_validTraps = CheckTraps();
49 return true;
50}

◆ SetDonor()

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

Definition at line 22 of file ComponentTcad2d.cc.

24 {
25 if (donorNumber >= m_donors.size()) {
26 std::cerr << m_className << "::SetDonor: Index out of range.\n";
27 return false;
28 }
29 m_donors[donorNumber].xsece = eXsec;
30 m_donors[donorNumber].xsech = hXsec;
31 m_donors[donorNumber].conc = conc;
32
33 m_validTraps = CheckTraps();
34 return true;
35}

◆ SetDriftRegion()

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

Definition at line 918 of file ComponentTcad2d.cc.

918 {
919 if (i >= m_regions.size()) {
920 std::cerr << m_className << "::SetDriftRegion: Index out of range.\n";
921 return;
922 }
923 m_regions[i].drift = true;
924}

◆ SetMedium()

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

Set the medium for a given region.

Definition at line 934 of file ComponentTcad2d.cc.

934 {
935 if (i >= m_regions.size()) {
936 std::cerr << m_className << "::SetMedium: Index out of range.\n";
937 return;
938 }
939
940 if (!medium) {
941 std::cerr << m_className << "::SetMedium: Null pointer.\n";
942 return;
943 }
944
945 m_regions[i].medium = medium;
946}

◆ SetRangeZ()

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

Definition at line 858 of file ComponentTcad2d.cc.

858 {
859 if (fabs(zmax - zmin) <= 0.) {
860 std::cerr << m_className << "::SetRangeZ: Zero range is not permitted.\n";
861 return;
862 }
863 m_zMinBB = std::min(zmin, zmax);
864 m_zMaxBB = std::max(zmin, zmax);
865 m_hasRangeZ = true;
866}

◆ SetWeightingField()

bool Garfield::ComponentTcad2d::SetWeightingField ( const std::string &  datfile1,
const std::string &  datfile2,
const double  dv 
)

Import field maps defining the 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.

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

Definition at line 766 of file ComponentTcad2d.cc.

768 {
769
770 if (!m_ready) {
771 std::cerr << m_className << "::SetWeightingField:\n"
772 << " Mesh is not available. Call Initialise first.\n";
773 return false;
774 }
775 if (dv < Small) {
776 std::cerr << m_className << "::SetWeightingField:\n"
777 << " Voltage difference must be > 0.\n";
778 return false;
779 }
780 const double s = 1. / dv;
781
782 m_wf.clear();
783 m_wp.clear();
784 // Load first the field/potential at nominal bias.
785 std::vector<std::array<double, 2> > wf1;
786 std::vector<double> wp1;
787 if (!LoadWeightingField(datfile1, wf1, wp1)) {
788 std::cerr << m_className << "::SetWeightingField:\n"
789 << " Could not import data from " << datfile1 << ".\n";
790 return false;
791 }
792 // Then load the field/potential for the configuration with the potential
793 // at the electrode to be read out increased by small voltage dv.
794 std::vector<std::array<double, 2> > wf2;
795 std::vector<double> wy2;
796 std::vector<double> wp2;
797 if (!LoadWeightingField(datfile2, wf2, wp2)) {
798 std::cerr << m_className << "::SetWeightingField:\n"
799 << " Could not import data from " << datfile2 << ".\n";
800 return false;
801 }
802 const unsigned int nVertices = m_vertices.size();
803 bool foundField = true;
804 if (wf1.size() != nVertices || wf2.size() != nVertices) {
805 foundField = false;
806 std::cerr << m_className << "::SetWeightingField:\n"
807 << " Could not load electric field values.\n";
808 }
809 bool foundPotential = true;
810 if (wp1.size() != nVertices || wp2.size() != nVertices) {
811 foundPotential = false;
812 std::cerr << m_className << "::SetWeightingField:\n"
813 << " Could not load electrostatic potentials.\n";
814 }
815 if (!foundField && !foundPotential) return false;
816 if (foundField) {
817 m_wf.assign(nVertices, {0., 0.});
818 for (unsigned int i = 0; i < nVertices; ++i) {
819 m_wf[i][0] = (wf2[i][0] - wf1[i][0]) * s;
820 m_wf[i][1] = (wf2[i][1] - wf1[i][1]) * s;
821 }
822 }
823 if (foundPotential) {
824 m_wp.assign(nVertices, 0.);
825 for (unsigned int i = 0; i < nVertices; ++i) {
826 m_wp[i] = (wp2[i] - wp1[i]) * s;
827 }
828 }
829 return true;
830}

◆ UnsetDriftRegion()

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

Definition at line 926 of file ComponentTcad2d.cc.

926 {
927 if (i >= m_regions.size()) {
928 std::cerr << m_className << "::UnsetDriftRegion: Index out of range.\n";
929 return;
930 }
931 m_regions[i].drift = false;
932}

◆ WeightingField()

void Garfield::ComponentTcad2d::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::ComponentBase.

Definition at line 118 of file ComponentTcad2d.cc.

120 {
121 wx = wy = wz = 0.;
122 if (m_wf.empty()) {
123 std::cerr << m_className << "::WeightingField: Not available.\n";
124 return;
125 }
126 // In case of periodicity, reduce to the cell volume.
127 double x = xin, y = yin, z = zin;
128 bool xmirr = false, ymirr = false;
129 MapCoordinates(x, y, xmirr, ymirr);
130 // Check if the point is inside the bounding box.
131 if (!InsideBoundingBox(x, y, z)) return;
132
133 std::array<double, nMaxVertices> w;
134 const unsigned int i = FindElement(x, y, w);
135 if (i >= m_elements.size()) return;
136
137 const Element& element = m_elements[i];
138 const unsigned int nVertices = element.type + 1;
139 for (unsigned int j = 0; j < nVertices; ++j) {
140 const auto& f = m_wf[element.vertex[j]];
141 wx += w[j] * f[0];
142 wy += w[j] * f[1];
143 }
144 if (xmirr) wx = -wx;
145 if (ymirr) wy = -wy;
146}

◆ WeightingPotential()

double Garfield::ComponentTcad2d::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::ComponentBase.

Definition at line 148 of file ComponentTcad2d.cc.

150 {
151
152 if (m_wp.empty()) {
153 std::cerr << m_className << "::WeightingPotential: Not available.\n";
154 return 0.;
155 }
156 // In case of periodicity, reduce to the cell volume.
157 double x = xin, y = yin, z = zin;
158 bool xmirr = false, ymirr = false;
159 MapCoordinates(x, y, xmirr, ymirr);
160 // Check if the point is inside the bounding box.
161 if (!InsideBoundingBox(x, y, z)) return 0.;
162
163 std::array<double, nMaxVertices> w;
164 const unsigned int i = FindElement(x, y, w);
165 if (i >= m_elements.size()) return 0.;
166
167 double v = 0.;
168 const Element& element = m_elements[i];
169 const unsigned int nVertices = element.type + 1;
170 for (unsigned int j = 0; j < nVertices; ++j) {
171 v += w[j] * m_wp[element.vertex[j]];
172 }
173 return v;
174}

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