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

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

#include <ComponentTcad3d.hh>

+ Inheritance diagram for Garfield::ComponentTcad3d:

Public Member Functions

 ComponentTcad3d ()
 
 ~ComponentTcad3d ()
 
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)
 
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.
 
bool Initialise (const std::string &gridfilename, const std::string &datafilename)
 
void PrintRegions ()
 
unsigned int GetNumberOfRegions () const
 
void GetRegion (const unsigned int ireg, 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)
 
bool GetMedium (const unsigned int ireg, Medium *&m) const
 
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 &node5, int &node6, int &node7, int &reg) const
 
unsigned int GetNumberOfNodes () const
 
bool GetNode (const unsigned int i, double &x, double &y, double &z, double &v, double &ex, double &ey, double &ez) const
 
- 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 three-dimensional field map created by Sentaurus Device.

Definition at line 10 of file ComponentTcad3d.hh.

Constructor & Destructor Documentation

◆ ComponentTcad3d()

Garfield::ComponentTcad3d::ComponentTcad3d ( )

Definition at line 22 of file ComponentTcad3d.cc.

22 : ComponentBase(),
23 m_pMin(0.),
24 m_pMax(0.),
25 m_lastElement(0) {
26
27 m_className = "ComponentTcad3d";
28
29 m_regions.reserve(10);
30 m_vertices.reserve(10000);
31 m_elements.reserve(10000);
32}
ComponentBase()
Constructor.
Definition: ComponentBase.cc:6
std::string m_className
Class name.

◆ ~ComponentTcad3d()

Garfield::ComponentTcad3d::~ComponentTcad3d ( )
inline

Definition at line 16 of file ComponentTcad3d.hh.

16{}

Member Function Documentation

◆ ElectricField() [1/2]

void Garfield::ComponentTcad3d::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 34 of file ComponentTcad3d.cc.

37 {
38
39 ex = ey = ez = p = 0.;
40 m = NULL;
41 // Make sure the field map has been loaded.
42 if (!m_ready) {
43 std::cerr << m_className << "::ElectricField:\n"
44 << " Field map is not available for interpolation.\n";
45 status = -10;
46 return;
47 }
48
49 double x = xin, y = yin, z = zin;
50 // In case of periodicity, reduce to the cell volume.
51 bool xmirr = false, ymirr = false, zmirr = false;
52 MapCoordinates(x, y, z, xmirr, ymirr, zmirr);
53
54 // Check if the point is inside the bounding box.
55 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB ||
56 z < m_zMinBB || z > m_zMaxBB) {
57 status = -11;
58 return;
59 }
60
61 // Assume this will work.
62 status = 0;
63 double w[nMaxVertices] = {0};
64 if (m_lastElement >= 0) {
65 // Check if the point is still located in the previously found element.
66 const Element& last = m_elements[m_lastElement];
67 if (x >= last.xmin && x <= last.xmax &&
68 y >= last.ymin && y <= last.ymax &&
69 z >= last.zmin && z <= last.zmax) {
70 if (CheckElement(x, y, z, last, w)) {
71 const unsigned int nVertices = last.type == 2 ? 3 : 4;
72 for (unsigned int j = 0; j < nVertices; ++j) {
73 const Vertex& vj = m_vertices[last.vertex[j]];
74 ex += w[j] * vj.ex;
75 ey += w[j] * vj.ey;
76 ez += w[j] * vj.ez;
77 p += w[j] * vj.p;
78 }
79 if (xmirr) ex = -ex;
80 if (ymirr) ey = -ey;
81 if (zmirr) ez = -ez;
82 m = m_regions[last.region].medium;
83 if (!m_regions[last.region].drift || !m) status = -5;
84 return;
85 }
86 }
87 // The point is not in the previous element.
88 // Check the adjacent elements.
89 const unsigned int nNeighbours = last.neighbours.size();
90 for (unsigned int i = 0; i < nNeighbours; ++i) {
91 const Element& element = m_elements[last.neighbours[i]];
92 if (x < element.xmin || x > element.xmax ||
93 y < element.ymin || y > element.ymax ||
94 z < element.zmin || z > element.zmax) continue;
95 if (!CheckElement(x, y, z, element, w)) continue;
96 const unsigned int nVertices = element.type == 2 ? 3 : 4;
97 for (unsigned int j = 0; j < nVertices; ++j) {
98 const Vertex& vj = m_vertices[element.vertex[j]];
99 ex += w[j] * vj.ex;
100 ey += w[j] * vj.ey;
101 ez += w[j] * vj.ez;
102 p += w[j] * vj.p;
103 }
104 if (xmirr) ex = -ex;
105 if (ymirr) ey = -ey;
106 if (zmirr) ez = -ez;
107 m = m_regions[element.region].medium;
108 if (!m_regions[element.region].drift || !m) status = -5;
109 m_lastElement = last.neighbours[i];
110 return;
111 }
112 }
113
114 // The point is not in the previous element.
115 // We have to loop over all elements.
116 const unsigned int nElements = m_elements.size();
117 for (unsigned int i = 0; i < nElements; ++i) {
118 const Element& element = m_elements[i];
119 if (x < element.xmin || x > element.xmax ||
120 y < element.ymin || y > element.ymax ||
121 z < element.zmin || z > element.zmax) continue;
122 if (!CheckElement(x, y, z, element, w)) continue;
123 const unsigned int nVertices = element.type == 2 ? 3 : 4;
124 for (unsigned int j = 0; j < nVertices; ++j) {
125 const Vertex& vj = m_vertices[element.vertex[j]];
126 ex += w[j] * vj.ex;
127 ey += w[j] * vj.ey;
128 ez += w[j] * vj.ez;
129 p += w[j] * vj.p;
130 }
131 if (xmirr) ex = -ex;
132 if (ymirr) ey = -ey;
133 if (zmirr) ez = -ez;
134 m = m_regions[element.region].medium;
135 if (!m_regions[element.region].drift || !m) status = -5;
136 m_lastElement = i;
137 return;
138 }
139
140 // Point is outside the mesh.
141 if (m_debug) {
142 std::cerr << m_className << "::ElectricField:\n"
143 << " Point (" << x << ", " << y << ", " << z
144 << ") is outside the mesh.\n";
145 }
146 status = -6;
147 return;
148}
bool m_ready
Ready for use?
bool m_debug
Switch on/off debugging messages.

Referenced by ElectricField().

◆ ElectricField() [2/2]

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

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 150 of file ComponentTcad3d.cc.

152 {
153
154 double v = 0.;
155 ElectricField(x, y, z, ex, ey, ez, v, m, status);
156}
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)

◆ GetBoundingBox()

bool Garfield::ComponentTcad3d::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 465 of file ComponentTcad3d.cc.

466 {
467
468 if (!m_ready) return false;
469 xmin = m_xMinBB;
470 ymin = m_yMinBB;
471 zmin = m_zMinBB;
472 xmax = m_xMaxBB;
473 ymax = m_yMaxBB;
474 zmax = m_zMaxBB;
476 xmin = -INFINITY;
477 xmax = +INFINITY;
478 }
480 ymin = -INFINITY;
481 ymax = +INFINITY;
482 }
484 zmin = -INFINITY;
485 zmax = +INFINITY;
486 }
487 return true;
488}
bool m_zMirrorPeriodic
Mirror periodicity in z.
bool m_yPeriodic
Simple periodicity in y.
bool m_yMirrorPeriodic
Mirror periodicity in y.
bool m_xPeriodic
Simple periodicity in x.
bool m_zPeriodic
Simple periodicity in z.
bool m_xMirrorPeriodic
Mirror periodicity in x.

◆ GetElement() [1/2]

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

Definition at line 592 of file ComponentTcad3d.cc.

594 {
595
596 if (i >= m_elements.size()) {
597 std::cerr << m_className << "::GetElement:\n"
598 << " Element index (" << i << ") out of range.\n";
599 return false;
600 }
601
602 const Element& element = m_elements[i];
603 if (element.type == 2) {
604 // Triangle
605 const Vertex& v0 = m_vertices[element.vertex[0]];
606 const Vertex& v1 = m_vertices[element.vertex[1]];
607 const Vertex& v2 = m_vertices[element.vertex[2]];
608 const double vx = (v1.y - v0.y) * (v2.z - v0.z) -
609 (v1.z - v0.z) * (v2.y - v0.y);
610 const double vy = (v1.z - v0.z) * (v2.x - v0.x) -
611 (v1.x - v0.x) * (v2.z - v0.z);
612 const double vz = (v1.x - v0.x) * (v2.y - v0.y) -
613 (v1.y - v0.y) * (v2.x - v0.x);
614 vol = sqrt(vx * vx + vy * vy + vz * vz);
615 const double a = sqrt(pow(v1.x - v0.x, 2) + pow(v1.y - v0.y, 2) +
616 pow(v1.z - v0.z, 2));
617 const double b = sqrt(pow(v2.x - v0.x, 2) + pow(v2.y - v0.y, 2) +
618 pow(v2.z - v0.z, 2));
619 const double c = sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) +
620 pow(v1.z - v2.z, 2));
621 dmin = dmax = a;
622 if (b < dmin) dmin = b;
623 if (c < dmin) dmin = c;
624 if (b > dmax) dmax = b;
625 if (c > dmax) dmax = c;
626 } else if (element.type == 5) {
627 // Tetrahedron
628 const Vertex& v0 = m_vertices[element.vertex[0]];
629 const Vertex& v1 = m_vertices[element.vertex[1]];
630 const Vertex& v2 = m_vertices[element.vertex[2]];
631 const Vertex& v3 = m_vertices[element.vertex[3]];
632 vol = fabs((v3.x - v0.x) * ((v1.y - v0.y) * (v2.z - v0.z) - (v2.y - v0.y) * (v1.z - v0.z)) +
633 (v3.y - v0.y) * ((v1.z - v0.z) * (v2.x - v0.x) - (v2.z - v0.z) * (v1.x - v0.x)) +
634 (v3.z - v0.z) * ((v1.x - v0.x) * (v2.y - v0.y) - (v3.x - v0.x) * (v1.y - v0.y))) / 6.;
635 // Loop over all pairs of m_vertices.
636 for (int j = 0; j < nMaxVertices - 1; ++j) {
637 const Vertex& vj = m_vertices[element.vertex[j]];
638 for (int k = j + 1; k < nMaxVertices; ++k) {
639 const Vertex& vk = m_vertices[element.vertex[k]];
640 // Compute distance.
641 const double dist = sqrt(pow(vj.x - vk.x, 2) + pow(vj.y - vk.y, 2) +
642 pow(vj.z - vk.z, 2));
643 if (k == 1) {
644 dmin = dmax = dist;
645 } else {
646 if (dist < dmin) dmin = dist;
647 if (dist > dmax) dmax = dist;
648 }
649 }
650 }
651 } else {
652 std::cerr << m_className << "::GetElement:\n"
653 << " Unexpected element type (" << type << ").\n";
654 return false;
655 }
656 return true;
657}
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::ComponentTcad3d::GetElement ( const unsigned int  i,
double &  vol,
double &  dmin,
double &  dmax,
int &  type,
int &  node1,
int &  node2,
int &  node3,
int &  node4,
int &  node5,
int &  node6,
int &  node7,
int &  reg 
) const

Definition at line 659 of file ComponentTcad3d.cc.

663 {
664
665 if (!GetElement(i, vol, dmin, dmax, type)) return false;
666 const Element& element = m_elements[i];
667 node1 = element.vertex[0];
668 node2 = element.vertex[1];
669 node3 = element.vertex[2];
670 node4 = element.vertex[3];
671 node5 = element.vertex[4];
672 node6 = element.vertex[5];
673 node7 = element.vertex[6];
674 reg = element.region;
675 return true;
676}
bool GetElement(const unsigned int i, double &vol, double &dmin, double &dmax, int &type) const

◆ GetMedium() [1/2]

Medium * Garfield::ComponentTcad3d::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 158 of file ComponentTcad3d.cc.

159 {
160
161 // Make sure the field map has been loaded.
162 if (!m_ready) {
163 std::cerr << m_className << "::GetMedium:\n"
164 << " Field map not available for interpolation.\n";
165 return NULL;
166 }
167
168 double x = xin, y = yin, z = zin;
169 bool xmirr = false, ymirr = false, zmirr = false;
170 MapCoordinates(x, y, z, xmirr, ymirr, zmirr);
171
172 // Check if the point is inside the bounding box.
173 if (x < m_xMinBB || x > m_xMaxBB || y < m_yMinBB || y > m_yMaxBB ||
174 z < m_zMinBB || z > m_zMaxBB) {
175 return NULL;
176 }
177
178 double w[nMaxVertices] = {0};
179 if (m_lastElement >= 0) {
180 // Check if the point is still located in the previously found element.
181 const Element& last = m_elements[m_lastElement];
182 if (x >= last.xmin && x <= last.xmax &&
183 y >= last.ymin && y <= last.ymax &&
184 z >= last.zmin && z <= last.zmax) {
185 if (CheckElement(x, y, z, last, w)) {
186 return m_regions[last.region].medium;
187 }
188 }
189
190 // The point is not in the previous element.
191 // Check the adjacent elements.
192 const unsigned int nNeighbours = last.neighbours.size();
193 for (unsigned int i = 0; i < nNeighbours; ++i) {
194 const Element& element = m_elements[last.neighbours[i]];
195 if (x < element.xmin || x > element.xmax ||
196 y < element.ymin || y > element.ymax ||
197 z < element.zmin || z > element.zmax) continue;
198 if (!CheckElement(x, y, z, element, w)) continue;
199 m_lastElement = last.neighbours[i];
200 return m_regions[element.region].medium;
201 }
202 }
203
204 // The point is not in the previous element nor in the adjacent ones.
205 // We have to loop over all elements.
206 const unsigned int nElements = m_elements.size();
207 for (unsigned int i = 0; i < nElements; ++i) {
208 const Element& element = m_elements[i];
209 if (x < element.xmin || x > element.xmax ||
210 y < element.ymin || y > element.ymax ||
211 z < element.zmin || z > element.zmax) continue;
212 if (!CheckElement(x, y, z, element, w)) continue;
213 m_lastElement = i;
214 return m_regions[element.region].medium;
215 }
216
217 // The point is outside the mesh.
218 return NULL;
219}

◆ GetMedium() [2/2]

bool Garfield::ComponentTcad3d::GetMedium ( const unsigned int  ireg,
Medium *&  m 
) const

Definition at line 579 of file ComponentTcad3d.cc.

579 {
580
581 if (i >= m_regions.size()) {
582 std::cerr << m_className << "::GetMedium:\n"
583 << " Region " << i << " does not exist.\n";
584 return false;
585 }
586
587 m = m_regions[i].medium;
588 if (!m) return false;
589 return true;
590}

◆ GetNode()

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

Definition at line 678 of file ComponentTcad3d.cc.

680 {
681
682 if (i >= m_vertices.size()) {
683 std::cerr << m_className << "::GetNode:\n"
684 << " Node index (" << i << ") out of range.\n";
685 return false;
686 }
687
688 const Vertex& vi = m_vertices[i];
689 x = vi.x;
690 y = vi.y;
691 z = vi.z;
692 v = vi.p;
693 ex = vi.ex;
694 ey = vi.ey;
695 ez = vi.ez;
696 return true;
697}

◆ GetNumberOfElements()

int Garfield::ComponentTcad3d::GetNumberOfElements ( ) const
inline

Definition at line 46 of file ComponentTcad3d.hh.

46{ return m_elements.size(); }

◆ GetNumberOfNodes()

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

Definition at line 52 of file ComponentTcad3d.hh.

52{ return m_vertices.size(); }

◆ GetNumberOfRegions()

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

Definition at line 37 of file ComponentTcad3d.hh.

37{ return m_regions.size(); }

◆ GetRegion()

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

Definition at line 532 of file ComponentTcad3d.cc.

533 {
534
535 if (i >= m_regions.size()) {
536 std::cerr << m_className << "::GetRegion:\n"
537 << " Region " << i << " does not exist.\n";
538 return;
539 }
540 name = m_regions[i].name;
541 active = m_regions[i].drift;
542}

◆ GetVoltageRange()

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

Calculate the voltage range [V].

Implements Garfield::ComponentBase.

Definition at line 490 of file ComponentTcad3d.cc.

490 {
491
492 if (!m_ready) return false;
493 vmin = m_pMin;
494 vmax = m_pMax;
495 return true;
496}

◆ Initialise()

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

Definition at line 221 of file ComponentTcad3d.cc.

222 {
223
224 m_ready = false;
225 // Import mesh data from .grd file.
226 if (!LoadGrid(gridfilename)) {
227 std::cerr << m_className << "::Initialise:\n"
228 << " Importing mesh data failed.\n";
229 return false;
230 }
231
232 // Import electric field and potential from .dat file.
233 if (!LoadData(datafilename)) {
234 std::cerr << m_className << "::Initialise:\n"
235 << " Importing electric field and potential failed.\n";
236 return false;
237 }
238
239 // Find min./max. coordinates and potentials.
240 m_xMaxBB = m_vertices[m_elements[0].vertex[0]].x;
241 m_yMaxBB = m_vertices[m_elements[0].vertex[0]].y;
242 m_zMaxBB = m_vertices[m_elements[0].vertex[0]].z;
243 m_xMinBB = m_xMaxBB;
244 m_yMinBB = m_yMaxBB;
245 m_zMinBB = m_zMaxBB;
246 m_pMax = m_pMin = m_vertices[m_elements[0].vertex[0]].p;
247 const unsigned int nElements = m_elements.size();
248 for (unsigned int i = 0; i < nElements; ++i) {
249 Element& element = m_elements[i];
250 double xmin = m_vertices[element.vertex[0]].x;
251 double ymin = m_vertices[element.vertex[0]].y;
252 double zmin = m_vertices[element.vertex[0]].z;
253 double xmax = xmin;
254 double ymax = ymin;
255 double zmax = zmin;
256 const unsigned int nVertices = element.type == 2 ? 3 : 4;
257 for (unsigned int j = 0; j < nVertices; ++j) {
258 const Vertex& vj = m_vertices[element.vertex[j]];
259 if (vj.x < xmin) xmin = vj.x;
260 if (vj.x > xmax) xmax = vj.x;
261 if (vj.y < ymin) ymin = vj.y;
262 if (vj.y > ymax) ymax = vj.y;
263 if (vj.z < zmin) zmin = vj.z;
264 if (vj.z > zmax) zmax = vj.z;
265 if (vj.p < m_pMin) m_pMin = vj.p;
266 if (vj.p > m_pMax) m_pMax = vj.p;
267 }
268 const double tol = 1.e-6;
269 element.xmin = xmin - tol;
270 element.xmax = xmax + tol;
271 element.ymin = ymin - tol;
272 element.ymax = ymax + tol;
273 element.zmin = zmin - tol;
274 element.zmax = zmax + tol;
275 m_xMinBB = std::min(m_xMinBB, xmin);
276 m_xMaxBB = std::max(m_xMaxBB, xmax);
277 m_yMinBB = std::min(m_yMinBB, ymin);
278 m_yMaxBB = std::max(m_yMaxBB, ymax);
279 m_zMinBB = std::min(m_zMinBB, zmin);
280 m_zMaxBB = std::max(m_zMaxBB, zmax);
281 }
282
283 std::cout << m_className << "::Initialise:\n"
284 << " Bounding box:\n"
285 << " " << m_xMinBB << " < x [cm] < " << m_xMaxBB << "\n"
286 << " " << m_yMinBB << " < y [cm] < " << m_yMaxBB << "\n"
287 << " " << m_zMinBB << " < z [cm] < " << m_zMaxBB << "\n"
288 << " Voltage range:\n"
289 << " " << m_pMin << " < V < " << m_pMax << "\n";
290
291 bool ok = true;
292
293 // Count the number of elements belonging to a region.
294 const int nRegions = m_regions.size();
295 std::vector<unsigned int> nElementsRegion(nRegions, 0);
296
297 // Count the different element shapes.
298 unsigned int nTriangles = 0;
299 unsigned int nTetrahedra = 0;
300 unsigned int nOtherShapes = 0;
301
302 // Check if there are elements which are not part of any region.
303 unsigned int nLoose = 0;
304 std::vector<int> looseElements;
305
306 // Check if there are degenerate elements.
307 unsigned int nDegenerate = 0;
308 std::vector<int> degenerateElements;
309
310 for (unsigned int i = 0; i < nElements; ++i) {
311 const Element& element = m_elements[i];
312 if (element.type == 2) {
313 ++nTriangles;
314 if (element.vertex[0] == element.vertex[1] ||
315 element.vertex[1] == element.vertex[2] ||
316 element.vertex[2] == element.vertex[0]) {
317 degenerateElements.push_back(i);
318 ++nDegenerate;
319 }
320 } else if (element.type == 5) {
321 if (element.vertex[0] == element.vertex[1] ||
322 element.vertex[0] == element.vertex[2] ||
323 element.vertex[0] == element.vertex[3] ||
324 element.vertex[1] == element.vertex[2] ||
325 element.vertex[1] == element.vertex[3] ||
326 element.vertex[2] == element.vertex[3]) {
327 degenerateElements.push_back(i);
328 ++nDegenerate;
329 }
330 ++nTetrahedra;
331 } else {
332 // Other shapes should not occur, since they were excluded in LoadGrid.
333 ++nOtherShapes;
334 }
335 if (element.region >= 0 && element.region < nRegions) {
336 ++nElementsRegion[element.region];
337 } else {
338 looseElements.push_back(i);
339 ++nLoose;
340 }
341 }
342
343 if (nDegenerate > 0) {
344 std::cerr << m_className << "::Initialise:\n"
345 << " The following elements are degenerate:\n";
346 for (unsigned int i = 0; i < nDegenerate; ++i) {
347 std::cerr << " " << degenerateElements[i] << "\n";
348 }
349 ok = false;
350 }
351
352 if (nLoose > 0) {
353 std::cerr << m_className << "::Initialise:\n"
354 << " The following elements are not part of any region:\n";
355 for (unsigned int i = 0; i < nLoose; ++i) {
356 std::cerr << " " << looseElements[i] << "\n";
357 }
358 ok = false;
359 }
360
361 std::cout << m_className << "::Initialise:\n"
362 << " Number of regions: " << nRegions << "\n";
363 for (int i = 0; i < nRegions; ++i) {
364 std::cout << " " << i << ": " << m_regions[i].name << ", "
365 << nElementsRegion[i] << " elements\n";
366 }
367
368 std::cout << " Number of elements: " << nElements << "\n";
369 if (nTriangles > 0) {
370 std::cout << " " << nTriangles << " triangles\n";
371 }
372 if (nTetrahedra > 0) {
373 std::cout << " " << nTetrahedra << " tetrahedra\n";
374 }
375 if (nOtherShapes > 0) {
376 std::cerr << " " << nOtherShapes << " elements of unknown type\n"
377 << " Program bug!\n";
378 m_ready = false;
379 Cleanup();
380 return false;
381 }
382 if (m_debug) {
383 // For each element, print the indices of the constituting vertices.
384 for (unsigned int i = 0; i < nElements; ++i) {
385 const Element& element = m_elements[i];
386 if (element.type == 2) {
387 std::cout << " " << i << ": " << element.vertex[0] << " "
388 << element.vertex[1] << " " << element.vertex[2]
389 << " (triangle, region " << element.region << ")\n";
390 } else if (element.type == 5) {
391 std::cout << " " << i << ": " << element.vertex[0] << " "
392 << element.vertex[1] << " " << element.vertex[2]
393 << " " << element.vertex[3] << " (tetrahedron, region "
394 << element.region << ")\n";
395 }
396 }
397 }
398
399 const unsigned int nVertices = m_vertices.size();
400 std::cout << " Number of vertices: " << nVertices << "\n";
401 if (m_debug) {
402 for (unsigned int i = 0; i < nVertices; ++i) {
403 const Vertex& vi = m_vertices[i];
404 std::cout << " " << i << ": (x, y, z) = (" << vi.x << ", "
405 << vi.y << ", " << vi.z << "), V = " << vi.p << "\n";
406 }
407 }
408
409 // Find adjacent elements.
410 std::cout << m_className << "::Initialise:\n"
411 << " Looking for neighbouring elements. Be patient...\n";
412 FindNeighbours();
413
414 if (!ok) {
415 m_ready = false;
416 Cleanup();
417 return false;
418 }
419
420 m_ready = true;
421 UpdatePeriodicity();
422 std::cout << m_className << "::Initialise:\n"
423 << " Initialisation finished.\n";
424 return true;
425}

◆ PrintRegions()

void Garfield::ComponentTcad3d::PrintRegions ( )

Definition at line 498 of file ComponentTcad3d.cc.

498 {
499
500 // Do not proceed if not properly initialised.
501 if (!m_ready) {
502 std::cerr << m_className << "::PrintRegions:\n"
503 << " Field map not yet initialised.\n";
504 return;
505 }
506
507 if (m_regions.empty()) {
508 std::cerr << m_className << "::PrintRegions:\n"
509 << " No regions are currently defined.\n";
510 return;
511 }
512
513 const unsigned int nRegions = m_regions.size();
514 std::cout << m_className << "::PrintRegions:\n"
515 << " Currently " << nRegions << " regions are defined.\n"
516 << " Index Name Medium\n";
517 for (unsigned int i = 0; i < nRegions; ++i) {
518 std::cout << " " << i << " " << m_regions[i].name;
519 if (!m_regions[i].medium) {
520 std::cout << " none ";
521 } else {
522 std::cout << " " << m_regions[i].medium->GetName();
523 }
524 if (m_regions[i].drift) {
525 std::cout << " (active region)\n";
526 } else {
527 std::cout << "\n";
528 }
529 }
530}

◆ SetDriftRegion()

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

Definition at line 544 of file ComponentTcad3d.cc.

544 {
545
546 if (i >= m_regions.size()) {
547 std::cerr << m_className << "::SetDriftRegion:\n"
548 << " Region " << i << " does not exist.\n";
549 return;
550 }
551 m_regions[i].drift = true;
552}

◆ SetMedium()

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

Definition at line 564 of file ComponentTcad3d.cc.

564 {
565
566 if (i >= m_regions.size()) {
567 std::cerr << m_className << "::SetMedium:\n"
568 << " Region " << i << " does not exist.\n";
569 return;
570 }
571
572 if (!medium) {
573 std::cerr << m_className << "::SetMedium:\n Null pointer.\n";
574 return;
575 }
576 m_regions[i].medium = medium;
577}

◆ UnsetDriftRegion()

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

Definition at line 554 of file ComponentTcad3d.cc.

554 {
555
556 if (i >= m_regions.size()) {
557 std::cerr << m_className << "::UnsetDriftRegion:\n"
558 << " Region " << i << " does not exist.\n";
559 return;
560 }
561 m_regions[i].drift = false;
562}

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