Garfield++ v1r0
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

#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)
 
MediumGetMedium (const double &x, const double &y, const double &z)
 
bool GetVoltageRange (double &vmin, double &vmax)
 
bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 
void SetRangeZ (const double zmin, const double zmax)
 
bool Initialise (const std::string gridfilename, const std::string datafilename)
 
void PrintRegions ()
 
int GetNumberOfRegions () const
 
void GetRegion (const int i, std::string &name, bool &active)
 
void SetDriftRegion (const int ireg)
 
void UnsetDriftRegion (const int ireg)
 
void SetMedium (const int ireg, Medium *m)
 
MediumGetMedium (const unsigned int &ireg) const
 
int GetNumberOfElements () const
 
bool GetElement (const int i, double &vol, double &dmin, double &dmax, int &type)
 
bool GetElement (const int i, double &vol, double &dmin, double &dmax, int &type, int &node1, int &node2, int &node3, int &node4, int &reg)
 
int GetNumberOfNodes () const
 
bool GetNode (const int i, double &x, double &y, double &v, double &ex, double &ey)
 
bool GetMobility (const double x, const double y, const double z, double &emob, double &hmob)
 
- Public Member Functions inherited from Garfield::ComponentBase
 ComponentBase ()
 
virtual ~ComponentBase ()
 
virtual void SetGeometry (GeometryBase *geo)
 
virtual void Clear ()
 
virtual MediumGetMedium (const double &x, const double &y, const double &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
 
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)
 
virtual bool IsReady ()
 
virtual bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 
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 (double x0, double y0, double z0, double &xw, double &yw, double &rw)
 
void EnablePeriodicityX ()
 
void DisablePeriodicityX ()
 
void EnablePeriodicityY ()
 
void DisablePeriodicityY ()
 
void EnablePeriodicityZ ()
 
void DisablePeriodicityZ ()
 
void EnableMirrorPeriodicityX ()
 
void DisableMirrorPeriodicityX ()
 
void EnableMirrorPeriodicityY ()
 
void DisableMirrorPeriodicityY ()
 
void EnableMirrorPeriodicityZ ()
 
void DisableMirrorPeriodicityZ ()
 
void EnableAxialPeriodicityX ()
 
void DisableAxialPeriodicityX ()
 
void EnableAxialPeriodicityY ()
 
void DisableAxialPeriodicityY ()
 
void EnableAxialPeriodicityZ ()
 
void DisableAxialPeriodicityZ ()
 
void EnableRotationSymmetryX ()
 
void DisableRotationSymmetryX ()
 
void EnableRotationSymmetryY ()
 
void DisableRotationSymmetryY ()
 
void EnableRotationSymmetryZ ()
 
void DisableRotationSymmetryZ ()
 
void EnableDebugging ()
 
void DisableDebugging ()
 

Additional Inherited Members

virtual void Reset ()=0
 
virtual void UpdatePeriodicity ()=0
 
- Protected Attributes inherited from Garfield::ComponentBase
std::string m_className
 
GeometryBasetheGeometry
 
bool ready
 
bool xPeriodic
 
bool yPeriodic
 
bool zPeriodic
 
bool xMirrorPeriodic
 
bool yMirrorPeriodic
 
bool zMirrorPeriodic
 
bool xAxiallyPeriodic
 
bool yAxiallyPeriodic
 
bool zAxiallyPeriodic
 
bool xRotationSymmetry
 
bool yRotationSymmetry
 
bool zRotationSymmetry
 
double bx0
 
double by0
 
double bz0
 
bool debug
 

Detailed Description

Definition at line 10 of file ComponentTcad2d.hh.

Constructor & Destructor Documentation

◆ ComponentTcad2d()

Garfield::ComponentTcad2d::ComponentTcad2d ( )

Definition at line 12 of file ComponentTcad2d.cc.

13 : ComponentBase(),
14 nRegions(0),
15 nVertices(0),
16 nElements(0),
17 hasPotential(false),
18 hasField(false),
19 hasElectronMobility(false),
20 hasHoleMobility(false),
21 pMin(0.),
22 pMax(0.),
23 hasRangeZ(false),
24 lastElement(0) {
25
26 m_className = "ComponentTcad2d";
27
28 regions.reserve(10);
29 regions.clear();
30 vertices.reserve(1000);
31 vertices.clear();
32 elements.reserve(1000);
33 elements.clear();
34 for (int i = nMaxVertices; i--;) w[i] = 0.;
35}

◆ ~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 37 of file ComponentTcad2d.cc.

40 {
41
42 m = 0;
43 // Make sure the field map has been loaded.
44 if (!ready) {
45 std::cerr << m_className << "::ElectricField:\n";
46 std::cerr << " Field map is not available for interpolation.\n";
47 status = -10;
48 return;
49 }
50
51 double x = xin, y = yin, z = zin;
52 // In case of periodicity, reduce to the cell volume.
53 bool xMirrored = false;
54 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
55 if (xPeriodic) {
56 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
57 if (x < xMinBoundingBox) x += cellsx;
58 } else if (xMirrorPeriodic) {
59 double xNew = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
60 if (xNew < xMinBoundingBox) xNew += cellsx;
61 int nx = int(floor(0.5 + (xNew - x) / cellsx));
62 if (nx != 2 * (nx / 2)) {
63 xNew = xMinBoundingBox + xMaxBoundingBox - xNew;
64 xMirrored = true;
65 }
66 x = xNew;
67 }
68 bool yMirrored = false;
69 const double cellsy = yMaxBoundingBox - yMinBoundingBox;
70 if (yPeriodic) {
71 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
72 if (y < yMinBoundingBox) y += cellsy;
73 } else if (yMirrorPeriodic) {
74 double yNew = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
75 if (yNew < yMinBoundingBox) yNew += cellsy;
76 int ny = int(floor(0.5 + (yNew - y) / cellsy));
77 if (ny != 2 * (ny / 2)) {
78 yNew = yMinBoundingBox + yMaxBoundingBox - yNew;
79 yMirrored = true;
80 }
81 y = yNew;
82 }
83
84 // Check if the point is inside the bounding box.
85 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
86 y > yMaxBoundingBox) {
87 status = -11;
88 return;
89 }
90 if (hasRangeZ) {
91 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
92 status = -11;
93 return;
94 }
95 }
96
97 // Initialise the electric field and potential.
98 ex = ey = ez = p = 0.;
99 // Assume this will work.
100 status = 0;
101 // Check if the point is still located in the previously found element.
102 int i = lastElement;
103 switch (elements[i].type) {
104 case 1:
105 if (CheckLine(x, y, i)) {
106 ex = w[0] * vertices[elements[i].vertex[0]].ex +
107 w[1] * vertices[elements[i].vertex[1]].ex;
108 ey = w[0] * vertices[elements[i].vertex[0]].ey +
109 w[1] * vertices[elements[i].vertex[1]].ey;
110 p = w[0] * vertices[elements[i].vertex[0]].p +
111 w[1] * vertices[elements[i].vertex[1]].p;
112 if (xMirrored) ex = -ex;
113 if (yMirrored) ey = -ey;
114 m = regions[elements[i].region].medium;
115 if (!regions[elements[i].region].drift || m == 0) status = -5;
116 return;
117 }
118 break;
119 case 2:
120 if (CheckTriangle(x, y, i)) {
121 ex = w[0] * vertices[elements[i].vertex[0]].ex +
122 w[1] * vertices[elements[i].vertex[1]].ex +
123 w[2] * vertices[elements[i].vertex[2]].ex;
124 ey = w[0] * vertices[elements[i].vertex[0]].ey +
125 w[1] * vertices[elements[i].vertex[1]].ey +
126 w[2] * vertices[elements[i].vertex[2]].ey;
127 p = w[0] * vertices[elements[i].vertex[0]].p +
128 w[1] * vertices[elements[i].vertex[1]].p +
129 w[2] * vertices[elements[i].vertex[2]].p;
130 if (xMirrored) ex = -ex;
131 if (yMirrored) ey = -ey;
132 m = regions[elements[i].region].medium;
133 if (!regions[elements[i].region].drift || m == 0) status = -5;
134 return;
135 }
136 break;
137 case 3:
138 if (CheckRectangle(x, y, i)) {
139 ex = w[0] * vertices[elements[i].vertex[0]].ex +
140 w[1] * vertices[elements[i].vertex[1]].ex +
141 w[2] * vertices[elements[i].vertex[2]].ex +
142 w[3] * vertices[elements[i].vertex[3]].ex;
143 ey = w[0] * vertices[elements[i].vertex[0]].ey +
144 w[1] * vertices[elements[i].vertex[1]].ey +
145 w[2] * vertices[elements[i].vertex[2]].ey +
146 w[3] * vertices[elements[i].vertex[3]].ey;
147 p = w[0] * vertices[elements[i].vertex[0]].p +
148 w[1] * vertices[elements[i].vertex[1]].p +
149 w[2] * vertices[elements[i].vertex[2]].p +
150 w[3] * vertices[elements[i].vertex[3]].p;
151 if (xMirrored) ex = -ex;
152 if (yMirrored) ey = -ey;
153 m = regions[elements[i].region].medium;
154 if (!regions[elements[i].region].drift || m == 0) status = -5;
155 return;
156 }
157 break;
158 default:
159 std::cerr << m_className << "::ElectricField:\n";
160 std::cerr << " Unknown element type (" << elements[i].type << ").\n";
161 status = -11;
162 return;
163 break;
164 }
165
166 // The point is not in the previous element.
167 // Check the adjacent elements.
168 for (int j = elements[lastElement].nNeighbours; j--;) {
169 i = elements[lastElement].neighbours[j];
170 if (x < vertices[elements[i].vertex[0]].x) continue;
171 switch (elements[i].type) {
172 case 1:
173 if (CheckLine(x, y, i)) {
174 ex = w[0] * vertices[elements[i].vertex[0]].ex +
175 w[1] * vertices[elements[i].vertex[1]].ex;
176 ey = w[0] * vertices[elements[i].vertex[0]].ey +
177 w[1] * vertices[elements[i].vertex[1]].ey;
178 p = w[0] * vertices[elements[i].vertex[0]].p +
179 w[1] * vertices[elements[i].vertex[1]].p;
180 if (xMirrored) ex = -ex;
181 if (yMirrored) ey = -ey;
182 lastElement = i;
183 m = regions[elements[i].region].medium;
184 if (!regions[elements[i].region].drift || m == 0) status = -5;
185 return;
186 }
187 break;
188 case 2:
189 if (CheckTriangle(x, y, i)) {
190 ex = w[0] * vertices[elements[i].vertex[0]].ex +
191 w[1] * vertices[elements[i].vertex[1]].ex +
192 w[2] * vertices[elements[i].vertex[2]].ex;
193 ey = w[0] * vertices[elements[i].vertex[0]].ey +
194 w[1] * vertices[elements[i].vertex[1]].ey +
195 w[2] * vertices[elements[i].vertex[2]].ey;
196 p = w[0] * vertices[elements[i].vertex[0]].p +
197 w[1] * vertices[elements[i].vertex[1]].p +
198 w[2] * vertices[elements[i].vertex[2]].p;
199 if (xMirrored) ex = -ex;
200 if (yMirrored) ey = -ey;
201 lastElement = i;
202 m = regions[elements[i].region].medium;
203 if (!regions[elements[i].region].drift || m == 0) status = -5;
204 return;
205 }
206 break;
207 case 3:
208 if (CheckRectangle(x, y, i)) {
209 ex = w[0] * vertices[elements[i].vertex[0]].ex +
210 w[1] * vertices[elements[i].vertex[1]].ex +
211 w[2] * vertices[elements[i].vertex[2]].ex +
212 w[3] * vertices[elements[i].vertex[3]].ex;
213 ey = w[0] * vertices[elements[i].vertex[0]].ey +
214 w[1] * vertices[elements[i].vertex[1]].ey +
215 w[2] * vertices[elements[i].vertex[2]].ey +
216 w[3] * vertices[elements[i].vertex[3]].ey;
217 p = w[0] * vertices[elements[i].vertex[0]].p +
218 w[1] * vertices[elements[i].vertex[1]].p +
219 w[2] * vertices[elements[i].vertex[2]].p +
220 w[3] * vertices[elements[i].vertex[3]].p;
221 if (xMirrored) ex = -ex;
222 if (yMirrored) ey = -ey;
223 lastElement = i;
224 m = regions[elements[i].region].medium;
225 if (!regions[elements[i].region].drift || m == 0) status = -5;
226 return;
227 }
228 break;
229 default:
230 std::cerr << m_className << "::ElectricField:\n";
231 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
232 status = -11;
233 return;
234 break;
235 }
236 }
237
238 // The point is not in the previous element nor in the adjacent ones.
239 // We have to loop over all elements.
240 for (i = nElements; i--;) {
241 if (x < vertices[elements[i].vertex[0]].x) continue;
242 switch (elements[i].type) {
243 case 1:
244 if (CheckLine(x, y, i)) {
245 ex = w[0] * vertices[elements[i].vertex[0]].ex +
246 w[1] * vertices[elements[i].vertex[1]].ex;
247 ey = w[0] * vertices[elements[i].vertex[0]].ey +
248 w[1] * vertices[elements[i].vertex[1]].ey;
249 p = w[0] * vertices[elements[i].vertex[0]].p +
250 w[1] * vertices[elements[i].vertex[1]].p;
251 if (xMirrored) ex = -ex;
252 if (yMirrored) ey = -ey;
253 lastElement = i;
254 m = regions[elements[i].region].medium;
255 if (!regions[elements[i].region].drift || m == 0) status = -5;
256 return;
257 }
258 break;
259 case 2:
260 if (CheckTriangle(x, y, i)) {
261 ex = w[0] * vertices[elements[i].vertex[0]].ex +
262 w[1] * vertices[elements[i].vertex[1]].ex +
263 w[2] * vertices[elements[i].vertex[2]].ex;
264 ey = w[0] * vertices[elements[i].vertex[0]].ey +
265 w[1] * vertices[elements[i].vertex[1]].ey +
266 w[2] * vertices[elements[i].vertex[2]].ey;
267 p = w[0] * vertices[elements[i].vertex[0]].p +
268 w[1] * vertices[elements[i].vertex[1]].p +
269 w[2] * vertices[elements[i].vertex[2]].p;
270 if (xMirrored) ex = -ex;
271 if (yMirrored) ey = -ey;
272 lastElement = i;
273 m = regions[elements[i].region].medium;
274 if (!regions[elements[i].region].drift || m == 0) status = -5;
275 return;
276 }
277 break;
278 case 3:
279 if (CheckRectangle(x, y, i)) {
280 ex = w[0] * vertices[elements[i].vertex[0]].ex +
281 w[1] * vertices[elements[i].vertex[1]].ex +
282 w[2] * vertices[elements[i].vertex[2]].ex +
283 w[3] * vertices[elements[i].vertex[3]].ex;
284 ey = w[0] * vertices[elements[i].vertex[0]].ey +
285 w[1] * vertices[elements[i].vertex[1]].ey +
286 w[2] * vertices[elements[i].vertex[2]].ey +
287 w[3] * vertices[elements[i].vertex[3]].ey;
288 p = w[0] * vertices[elements[i].vertex[0]].p +
289 w[1] * vertices[elements[i].vertex[1]].p +
290 w[2] * vertices[elements[i].vertex[2]].p +
291 w[3] * vertices[elements[i].vertex[3]].p;
292 if (xMirrored) ex = -ex;
293 if (yMirrored) ey = -ey;
294 lastElement = i;
295 m = regions[elements[i].region].medium;
296 if (!regions[elements[i].region].drift || m == 0) status = -5;
297 return;
298 }
299 break;
300 default:
301 std::cerr << m_className << "::ElectricField:\n";
302 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
303 status = -11;
304 return;
305 break;
306 }
307 }
308 // Point is outside the mesh.
309 if (debug) {
310 std::cerr << m_className << "::ElectricField:\n";
311 std::cerr << " Point (" << x << ", " << y << ") is outside the mesh.\n";
312 }
313 status = -6;
314 return;
315}

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

Implements Garfield::ComponentBase.

Definition at line 317 of file ComponentTcad2d.cc.

319 {
320
321 double v = 0.;
322 ElectricField(x, y, z, ex, ey, ez, v, m, status);
323}
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::ComponentTcad2d::GetBoundingBox ( double &  xmin,
double &  ymin,
double &  zmin,
double &  xmax,
double &  ymax,
double &  zmax 
)
virtual

Reimplemented from Garfield::ComponentBase.

Definition at line 854 of file ComponentTcad2d.cc.

855 {
856
857 if (!ready) return false;
858 if (xPeriodic || xMirrorPeriodic) {
859 xmin = -INFINITY;
860 xmax = +INFINITY;
861 } else {
862 xmin = xMinBoundingBox;
863 xmax = xMaxBoundingBox;
864 }
865
866 if (yPeriodic || yMirrorPeriodic) {
867 ymin = -INFINITY;
868 ymax = +INFINITY;
869 } else {
870 ymin = yMinBoundingBox;
871 ymax = yMaxBoundingBox;
872 }
873
874 if (hasRangeZ) {
875 zmin = zMinBoundingBox;
876 zmax = zMaxBoundingBox;
877 }
878 return true;
879}

◆ GetElement() [1/2]

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

Definition at line 993 of file ComponentTcad2d.cc.

994 {
995
996 if (i < 0 || i >= nElements) {
997 std::cerr << m_className << "::GetElement:\n";
998 std::cerr << " Element index (" << i << ") out of range.\n";
999 return false;
1000 }
1001
1002 type = elements[i].type;
1003 if (elements[i].type == 1) {
1004 const double d = sqrt(pow(vertices[elements[i].vertex[1]].x -
1005 vertices[elements[i].vertex[0]].x,
1006 2) +
1007 pow(vertices[elements[i].vertex[1]].y -
1008 vertices[elements[i].vertex[0]].y,
1009 2));
1010 dmin = dmax = vol = d;
1011 } else if (elements[i].type == 2) {
1012 vol = fabs((vertices[elements[i].vertex[2]].x -
1013 vertices[elements[i].vertex[0]].x) *
1014 (vertices[elements[i].vertex[1]].y -
1015 vertices[elements[i].vertex[0]].y) -
1016 (vertices[elements[i].vertex[2]].y -
1017 vertices[elements[i].vertex[0]].y) *
1018 (vertices[elements[i].vertex[1]].x -
1019 vertices[elements[i].vertex[0]].x)) /
1020 2.;
1021 const double a = sqrt(pow(vertices[elements[i].vertex[1]].x -
1022 vertices[elements[i].vertex[0]].x,
1023 2) +
1024 pow(vertices[elements[i].vertex[1]].y -
1025 vertices[elements[i].vertex[0]].y,
1026 2));
1027 const double b = sqrt(pow(vertices[elements[i].vertex[2]].x -
1028 vertices[elements[i].vertex[0]].x,
1029 2) +
1030 pow(vertices[elements[i].vertex[2]].y -
1031 vertices[elements[i].vertex[0]].y,
1032 2));
1033 const double c = sqrt(pow(vertices[elements[i].vertex[1]].x -
1034 vertices[elements[i].vertex[2]].x,
1035 2) +
1036 pow(vertices[elements[i].vertex[1]].y -
1037 vertices[elements[i].vertex[2]].y,
1038 2));
1039 dmin = dmax = a;
1040 if (b > dmax) dmax = b;
1041 if (c > dmax) dmax = c;
1042 if (b < dmin) dmin = b;
1043 if (c < dmin) dmin = c;
1044 } else if (elements[i].type == 3) {
1045 const double a = sqrt(pow(vertices[elements[i].vertex[1]].x -
1046 vertices[elements[i].vertex[0]].x,
1047 2) +
1048 pow(vertices[elements[i].vertex[1]].y -
1049 vertices[elements[i].vertex[0]].y,
1050 2));
1051 const double b = sqrt(pow(vertices[elements[i].vertex[3]].x -
1052 vertices[elements[i].vertex[0]].x,
1053 2) +
1054 pow(vertices[elements[i].vertex[3]].y -
1055 vertices[elements[i].vertex[0]].y,
1056 2));
1057 vol = a * b;
1058 dmin = std::min(a, b);
1059 dmax = sqrt(a * a + b * b);
1060 } else {
1061 std::cerr << m_className << "::GetElement:\n";
1062 std::cerr << " Unexpected element type (" << type << ")\n";
1063 return false;
1064 }
1065 return true;
1066}
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:616

Referenced by GetElement().

◆ GetElement() [2/2]

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

Definition at line 1068 of file ComponentTcad2d.cc.

1070 {
1071
1072 if (!GetElement(i, vol, dmin, dmax, type)) return false;
1073 node1 = elements[i].vertex[0];
1074 node2 = elements[i].vertex[1];
1075 node3 = elements[i].vertex[2];
1076 node4 = elements[i].vertex[3];
1077 reg = elements[i].region;
1078 return true;
1079}
bool GetElement(const int i, double &vol, double &dmin, double &dmax, int &type)

◆ GetMedium() [1/2]

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

Reimplemented from Garfield::ComponentBase.

Definition at line 325 of file ComponentTcad2d.cc.

326 {
327
328 // Make sure the field map has been loaded.
329 if (!ready) {
330 std::cerr << m_className << "::GetMedium:\n";
331 std::cerr << " Field map not available for interpolation.\n";
332 return NULL;
333 }
334
335 double x = xin, y = yin, z = zin;
336 // In case of periodicity, reduce to the cell volume.
337 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
338 if (xPeriodic) {
339 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
340 if (x < xMinBoundingBox) x += cellsx;
341 } else if (xMirrorPeriodic) {
342 double xNew = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
343 if (xNew < xMinBoundingBox) xNew += cellsx;
344 int nx = int(floor(0.5 + (xNew - x) / cellsx));
345 if (nx != 2 * (nx / 2)) {
346 xNew = xMinBoundingBox + xMaxBoundingBox - xNew;
347 }
348 x = xNew;
349 }
350 const double cellsy = yMaxBoundingBox - yMinBoundingBox;
351 if (yPeriodic) {
352 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
353 if (y < yMinBoundingBox) y += cellsy;
354 } else if (yMirrorPeriodic) {
355 double yNew = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
356 if (yNew < yMinBoundingBox) yNew += cellsy;
357 int ny = int(floor(0.5 + (yNew - y) / cellsy));
358 if (ny != 2 * (ny / 2)) {
359 yNew = yMinBoundingBox + yMaxBoundingBox - yNew;
360 }
361 y = yNew;
362 }
363
364 // Check if the point is inside the bounding box.
365 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
366 y > yMaxBoundingBox) {
367 return NULL;
368 }
369 if (hasRangeZ) {
370 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
371 return NULL;
372 }
373 }
374
375 // Check if the point is still located in the previous element.
376 int i = lastElement;
377 switch (elements[i].type) {
378 case 1:
379 if (CheckLine(x, y, i)) {
380 return regions[elements[i].region].medium;
381 }
382 break;
383 case 2:
384 if (CheckTriangle(x, y, i)) {
385 return regions[elements[i].region].medium;
386 }
387 break;
388 case 3:
389 if (CheckRectangle(x, y, i)) {
390 return regions[elements[i].region].medium;
391 }
392 break;
393 default:
394 std::cerr << m_className << "::GetMedium:\n";
395 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
396 return NULL;
397 break;
398 }
399
400 // The point is not in the previous element.
401 // Check the adjacent elements.
402 for (int j = elements[lastElement].nNeighbours; j--;) {
403 i = elements[lastElement].neighbours[j];
404 if (x < vertices[elements[i].vertex[0]].x) continue;
405 switch (elements[i].type) {
406 case 1:
407 if (CheckLine(x, y, i)) {
408 lastElement = i;
409 return regions[elements[i].region].medium;
410 }
411 break;
412 case 2:
413 if (CheckTriangle(x, y, i)) {
414 lastElement = i;
415 return regions[elements[i].region].medium;
416 }
417 break;
418 case 3:
419 if (CheckRectangle(x, y, i)) {
420 lastElement = i;
421 return regions[elements[i].region].medium;
422 }
423 break;
424 default:
425 std::cerr << m_className << "::GetMedium:\n";
426 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
427 return NULL;
428 break;
429 }
430 }
431
432 // The point is not in the previous element nor in the adjacent ones.
433 // We have to loop over all elements.
434 for (i = nElements; i--;) {
435 if (x < vertices[elements[i].vertex[0]].x) continue;
436 switch (elements[i].type) {
437 case 1:
438 if (CheckLine(x, y, i)) {
439 lastElement = i;
440 return regions[elements[i].region].medium;
441 }
442 break;
443 case 2:
444 if (CheckTriangle(x, y, i)) {
445 lastElement = i;
446 return regions[elements[i].region].medium;
447 }
448 break;
449 case 3:
450 if (CheckRectangle(x, y, i)) {
451 lastElement = i;
452 return regions[elements[i].region].medium;
453 }
454 break;
455 default:
456 std::cerr << m_className << "::GetMedium:\n";
457 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
458 return NULL;
459 break;
460 }
461 }
462 // The point is outside the mesh.
463 return NULL;
464}

◆ GetMedium() [2/2]

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

Definition at line 982 of file ComponentTcad2d.cc.

982 {
983
984 if (i >= (unsigned int)nRegions) {
985 std::cerr << m_className << "::GetMedium:\n";
986 std::cerr << " Region " << i << " does not exist.\n";
987 return NULL;
988 }
989
990 return regions[i].medium;
991}

◆ GetMobility()

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

Definition at line 466 of file ComponentTcad2d.cc.

468 {
469
470 emob = hmob = 0.;
471 // Make sure the field map has been loaded.
472 if (!ready) {
473 std::cerr << m_className << "::GetMobility:\n";
474 std::cerr << " Field map is not available for interpolation.\n";
475 return false;
476 }
477
478 double x = xin, y = yin, z = zin;
479 // In case of periodicity, reduce to the cell volume.
480 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
481 if (xPeriodic) {
482 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
483 if (x < xMinBoundingBox) x += cellsx;
484 } else if (xMirrorPeriodic) {
485 double xNew = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
486 if (xNew < xMinBoundingBox) xNew += cellsx;
487 int nx = int(floor(0.5 + (xNew - x) / cellsx));
488 if (nx != 2 * (nx / 2)) {
489 xNew = xMinBoundingBox + xMaxBoundingBox - xNew;
490 }
491 x = xNew;
492 }
493 const double cellsy = xMaxBoundingBox - xMinBoundingBox;
494 if (yPeriodic) {
495 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
496 if (y < yMinBoundingBox) y += cellsy;
497 } else if (yMirrorPeriodic) {
498 double yNew = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
499 if (yNew < yMinBoundingBox) yNew += cellsy;
500 int ny = int(floor(0.5 + (yNew - y) / cellsy));
501 if (ny != 2 * (ny / 2)) {
502 yNew = yMinBoundingBox + yMaxBoundingBox - yNew;
503 }
504 y = yNew;
505 }
506
507 // Check if the point is inside the bounding box.
508 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
509 y > yMaxBoundingBox) {
510 return false;
511 }
512 if (hasRangeZ) {
513 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
514 return false;
515 }
516 }
517
518 // Check if the point is still located in the previously found element.
519 int i = lastElement;
520 switch (elements[i].type) {
521 case 1:
522 if (CheckLine(x, y, i)) {
523 emob = w[0] * vertices[elements[i].vertex[0]].emob +
524 w[1] * vertices[elements[i].vertex[1]].emob;
525 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
526 w[1] * vertices[elements[i].vertex[1]].hmob;
527 return true;
528 }
529 break;
530 case 2:
531 if (CheckTriangle(x, y, i)) {
532 emob = w[0] * vertices[elements[i].vertex[0]].emob +
533 w[1] * vertices[elements[i].vertex[1]].emob +
534 w[2] * vertices[elements[i].vertex[2]].emob;
535 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
536 w[1] * vertices[elements[i].vertex[1]].hmob +
537 w[2] * vertices[elements[i].vertex[2]].hmob;
538 return true;
539 }
540 break;
541 case 3:
542 if (CheckRectangle(x, y, i)) {
543 emob = w[0] * vertices[elements[i].vertex[0]].emob +
544 w[1] * vertices[elements[i].vertex[1]].emob +
545 w[2] * vertices[elements[i].vertex[2]].emob +
546 w[3] * vertices[elements[i].vertex[3]].emob;
547 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
548 w[1] * vertices[elements[i].vertex[1]].hmob +
549 w[2] * vertices[elements[i].vertex[2]].hmob +
550 w[3] * vertices[elements[i].vertex[3]].hmob;
551 return true;
552 }
553 break;
554 default:
555 std::cerr << m_className << "::GetMobility:\n";
556 std::cerr << " Unknown element type (" << elements[i].type << ").\n";
557 return false;
558 break;
559 }
560
561 // The point is not in the previous element.
562 // Check the adjacent elements.
563 for (int j = elements[lastElement].nNeighbours; j--;) {
564 i = elements[lastElement].neighbours[j];
565 if (x < vertices[elements[i].vertex[0]].x) continue;
566 switch (elements[i].type) {
567 case 1:
568 if (CheckLine(x, y, i)) {
569 emob = w[0] * vertices[elements[i].vertex[0]].emob +
570 w[1] * vertices[elements[i].vertex[1]].emob;
571 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
572 w[1] * vertices[elements[i].vertex[1]].hmob;
573 lastElement = i;
574 return true;
575 }
576 break;
577 case 2:
578 if (CheckTriangle(x, y, i)) {
579 emob = w[0] * vertices[elements[i].vertex[0]].emob +
580 w[1] * vertices[elements[i].vertex[1]].emob +
581 w[2] * vertices[elements[i].vertex[2]].emob;
582 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
583 w[1] * vertices[elements[i].vertex[1]].hmob +
584 w[2] * vertices[elements[i].vertex[2]].hmob;
585 lastElement = i;
586 return true;
587 }
588 break;
589 case 3:
590 if (CheckRectangle(x, y, i)) {
591 emob = w[0] * vertices[elements[i].vertex[0]].emob +
592 w[1] * vertices[elements[i].vertex[1]].emob +
593 w[2] * vertices[elements[i].vertex[2]].emob +
594 w[3] * vertices[elements[i].vertex[3]].emob;
595 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
596 w[1] * vertices[elements[i].vertex[1]].hmob +
597 w[2] * vertices[elements[i].vertex[2]].hmob +
598 w[3] * vertices[elements[i].vertex[3]].hmob;
599 lastElement = i;
600 return true;
601 }
602 break;
603 default:
604 std::cerr << m_className << "::GetMobility:\n";
605 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
606 return false;
607 break;
608 }
609 }
610
611 // The point is not in the previous element nor in the adjacent ones.
612 // We have to loop over all elements.
613 for (i = nElements; i--;) {
614 if (x < vertices[elements[i].vertex[0]].x) continue;
615 switch (elements[i].type) {
616 case 1:
617 if (CheckLine(x, y, i)) {
618 emob = w[0] * vertices[elements[i].vertex[0]].emob +
619 w[1] * vertices[elements[i].vertex[1]].emob;
620 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
621 w[1] * vertices[elements[i].vertex[1]].hmob;
622 lastElement = i;
623 return true;
624 }
625 break;
626 case 2:
627 if (CheckTriangle(x, y, i)) {
628 emob = w[0] * vertices[elements[i].vertex[0]].emob +
629 w[1] * vertices[elements[i].vertex[1]].emob +
630 w[2] * vertices[elements[i].vertex[2]].emob;
631 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
632 w[1] * vertices[elements[i].vertex[1]].hmob +
633 w[2] * vertices[elements[i].vertex[2]].hmob;
634 lastElement = i;
635 return true;
636 }
637 break;
638 case 3:
639 if (CheckRectangle(x, y, i)) {
640 emob = w[0] * vertices[elements[i].vertex[0]].emob +
641 w[1] * vertices[elements[i].vertex[1]].emob +
642 w[2] * vertices[elements[i].vertex[2]].emob +
643 w[3] * vertices[elements[i].vertex[3]].emob;
644 hmob = w[0] * vertices[elements[i].vertex[0]].hmob +
645 w[1] * vertices[elements[i].vertex[1]].hmob +
646 w[2] * vertices[elements[i].vertex[2]].hmob +
647 w[3] * vertices[elements[i].vertex[3]].hmob;
648 lastElement = i;
649 return true;
650 }
651 break;
652 default:
653 std::cerr << m_className << "::GetMobility:\n";
654 std::cerr << " Invalid element type (" << elements[i].type << ").\n";
655 return false;
656 break;
657 }
658 }
659 // Point is outside the mesh.
660 if (debug) {
661 std::cerr << m_className << "::GetMobility:\n";
662 std::cerr << " Point (" << x << ", " << y << ") is outside the mesh.\n";
663 }
664 return false;
665}

◆ GetNode()

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

Definition at line 1081 of file ComponentTcad2d.cc.

1082 {
1083
1084 if (i < 0 || i >= nVertices) {
1085 std::cerr << m_className << "::GetNode:\n";
1086 std::cerr << " Node index (" << i << ") out of range.\n";
1087 return false;
1088 }
1089
1090 x = vertices[i].x;
1091 y = vertices[i].y;
1092 v = vertices[i].p;
1093 ex = vertices[i].ex;
1094 ey = vertices[i].ey;
1095 return true;
1096}

◆ GetNumberOfElements()

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

Definition at line 47 of file ComponentTcad2d.hh.

47{ return nElements; }

◆ GetNumberOfNodes()

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

Definition at line 53 of file ComponentTcad2d.hh.

53{ return nVertices; }

◆ GetNumberOfRegions()

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

Definition at line 38 of file ComponentTcad2d.hh.

38{ return nRegions; }

◆ GetRegion()

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

Definition at line 934 of file ComponentTcad2d.cc.

934 {
935
936 if (i < 0 || i >= nRegions) {
937 std::cerr << m_className << "::GetRegion:\n";
938 std::cerr << " Region " << i << " does not exist.\n";
939 return;
940 }
941 name = regions[i].name;
942 active = regions[i].drift;
943}

◆ GetVoltageRange()

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

Implements Garfield::ComponentBase.

Definition at line 893 of file ComponentTcad2d.cc.

893 {
894
895 if (!ready) return false;
896 vmin = pMin;
897 vmax = pMax;
898 return true;
899}

◆ Initialise()

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

Definition at line 667 of file ComponentTcad2d.cc.

668 {
669
670 ready = false;
671 // Import mesh data from .grd file.
672 if (!LoadGrid(gridfilename)) {
673 std::cerr << m_className << "::Initialise:\n";
674 std::cerr << " Importing mesh data failed.\n";
675 return false;
676 }
677
678 hasPotential = hasField = false;
679 hasElectronMobility = hasHoleMobility = false;
680
681 // Import electric field and potential from .dat file.
682 if (!LoadData(datafilename)) {
683 std::cerr << m_className << "::Initialise:\n";
684 std::cerr << " Importing electric field and potential failed.\n";
685 return false;
686 }
687
688 // Find min./max. coordinates and potentials.
689 xMaxBoundingBox = xMinBoundingBox = vertices[elements[0].vertex[0]].x;
690 yMaxBoundingBox = yMinBoundingBox = vertices[elements[0].vertex[0]].y;
691 pMax = pMin = vertices[elements[0].vertex[0]].p;
692 for (int i = nElements; i--;) {
693 for (int j = 0; j <= elements[i].type; ++j) {
694 if (vertices[elements[i].vertex[j]].x < xMinBoundingBox) {
695 xMinBoundingBox = vertices[elements[i].vertex[j]].x;
696 } else if (vertices[elements[i].vertex[j]].x > xMaxBoundingBox) {
697 xMaxBoundingBox = vertices[elements[i].vertex[j]].x;
698 }
699 if (vertices[elements[i].vertex[j]].y < yMinBoundingBox) {
700 yMinBoundingBox = vertices[elements[i].vertex[j]].y;
701 } else if (vertices[elements[i].vertex[j]].y > yMaxBoundingBox) {
702 yMaxBoundingBox = vertices[elements[i].vertex[j]].y;
703 }
704 if (vertices[elements[i].vertex[j]].p < pMin) {
705 pMin = vertices[elements[i].vertex[j]].p;
706 } else if (vertices[elements[i].vertex[j]].p > pMax) {
707 pMax = vertices[elements[i].vertex[j]].p;
708 }
709 }
710 }
711
712 std::cout << m_className << "::Initialise:\n";
713 std::cout << " Available data:\n";
714 if (hasPotential) {
715 std::cout << " Electrostatic potential\n";
716 }
717 if (hasField) {
718 std::cout << " Electric field\n";
719 }
720 if (hasElectronMobility) {
721 std::cout << " Electron mobility\n";
722 }
723 if (hasHoleMobility) {
724 std::cout << " Hole mobility\n";
725 }
726 std::cout << " Bounding box:\n";
727 std::cout << " " << xMinBoundingBox << " < x [cm] < " << xMaxBoundingBox
728 << "\n";
729 std::cout << " " << yMinBoundingBox << " < y [cm] < " << yMaxBoundingBox
730 << "\n";
731 std::cout << " Voltage range:\n";
732 std::cout << " " << pMin << " < V < " << pMax << "\n";
733
734 bool ok = true;
735
736 // Count the number of elements belonging to a region.
737 std::vector<int> nElementsRegion;
738 nElementsRegion.resize(nRegions);
739 for (int i = nRegions; i--;) nElementsRegion[i] = 0;
740
741 // Count the different element shapes.
742 int nLines = 0;
743 int nTriangles = 0;
744 int nRectangles = 0;
745 int nOtherShapes = 0;
746
747 // Check if there are elements which are not part of any region.
748 int nLoose = 0;
749 std::vector<int> looseElements;
750 looseElements.clear();
751
752 // Check if there are degenerate elements.
753 int nDegenerate = 0;
754 std::vector<int> degenerateElements;
755 degenerateElements.clear();
756
757 for (int i = nElements; i--;) {
758 if (elements[i].type == 1) {
759 ++nLines;
760 if (elements[i].vertex[0] == elements[i].vertex[1]) {
761 degenerateElements.push_back(i);
762 ++nDegenerate;
763 }
764 } else if (elements[i].type == 2) {
765 ++nTriangles;
766 if (elements[i].vertex[0] == elements[i].vertex[1] ||
767 elements[i].vertex[1] == elements[i].vertex[2] ||
768 elements[i].vertex[2] == elements[i].vertex[0]) {
769 degenerateElements.push_back(i);
770 ++nDegenerate;
771 }
772 } else if (elements[i].type == 3) {
773 ++nRectangles;
774 if (elements[i].vertex[0] == elements[i].vertex[1] ||
775 elements[i].vertex[0] == elements[i].vertex[2] ||
776 elements[i].vertex[0] == elements[i].vertex[3] ||
777 elements[i].vertex[1] == elements[i].vertex[2] ||
778 elements[i].vertex[1] == elements[i].vertex[3] ||
779 elements[i].vertex[2] == elements[i].vertex[3]) {
780 degenerateElements.push_back(i);
781 ++nDegenerate;
782 }
783 } else {
784 // Other shapes should not occur, since they were excluded in LoadGrid.
785 ++nOtherShapes;
786 }
787 if (elements[i].region >= 0 && elements[i].region < nRegions) {
788 ++nElementsRegion[elements[i].region];
789 } else {
790 looseElements.push_back(i);
791 ++nLoose;
792 }
793 }
794
795 if (nDegenerate > 0) {
796 std::cerr << m_className << "::Initialise:\n";
797 std::cerr << " The following elements are degenerate:\n";
798 for (int i = nDegenerate; i--;) {
799 std::cerr << " " << degenerateElements[i] << "\n";
800 }
801 ok = false;
802 }
803
804 if (nLoose > 0) {
805 std::cerr << m_className << "::Initialise:\n";
806 std::cerr << " The following elements are not part of any region:\n";
807 for (int i = nLoose; i--;) {
808 std::cerr << " " << looseElements[i] << "\n";
809 }
810 ok = false;
811 }
812
813 std::cout << m_className << "::Initialise:\n";
814 std::cout << " Number of regions: " << nRegions << "\n";
815 for (int i = 0; i < nRegions; ++i) {
816 std::cout << " " << i << ": " << regions[i].name << ", "
817 << nElementsRegion[i] << " elements\n";
818 }
819
820 std::cout << " Number of elements: " << nElements << "\n";
821 if (nLines > 0) {
822 std::cout << " " << nLines << " lines\n";
823 }
824 if (nTriangles > 0) {
825 std::cout << " " << nTriangles << " triangles\n";
826 }
827 if (nRectangles > 0) {
828 std::cout << " " << nRectangles << " rectangles\n";
829 }
830 if (nOtherShapes > 0) {
831 std::cout << " " << nOtherShapes << " elements of unknown type\n";
832 std::cout << " Program bug!\n";
833 ready = false;
834 Cleanup();
835 return false;
836 }
837
838 std::cout << " Number of vertices: " << nVertices << "\n";
839
840 // Find adjacent elements.
841 FindNeighbours();
842
843 if (!ok) {
844 ready = false;
845 Cleanup();
846 return false;
847 }
848
849 ready = true;
850 UpdatePeriodicity();
851 return true;
852}

◆ PrintRegions()

void Garfield::ComponentTcad2d::PrintRegions ( )

Definition at line 901 of file ComponentTcad2d.cc.

901 {
902
903 // Do not proceed if not properly initialised.
904 if (!ready) {
905 std::cerr << m_className << "::PrintRegions:\n";
906 std::cerr << " Field map not yet initialised.\n";
907 return;
908 }
909
910 if (nRegions < 0) {
911 std::cerr << m_className << "::PrintRegions:\n";
912 std::cerr << " No regions are currently defined.\n";
913 return;
914 }
915
916 std::cout << m_className << "::PrintRegions:\n";
917 std::cout << " Currently " << nRegions << " regions are defined.\n";
918 std::cout << " Index Name Medium\n";
919 for (int i = 0; i < nRegions; ++i) {
920 std::cout << " " << i << " " << regions[i].name;
921 if (regions[i].medium == 0) {
922 std::cout << " none ";
923 } else {
924 std::cout << " " << regions[i].medium->GetName();
925 }
926 if (regions[i].drift) {
927 std::cout << " (active region)\n";
928 } else {
929 std::cout << "\n";
930 }
931 }
932}

◆ SetDriftRegion()

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

Definition at line 945 of file ComponentTcad2d.cc.

945 {
946
947 if (i < 0 || i >= nRegions) {
948 std::cerr << m_className << "::SetDriftRegion:\n";
949 std::cerr << " Region " << i << " does not exist.\n";
950 return;
951 }
952 regions[i].drift = true;
953}

◆ SetMedium()

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

Definition at line 965 of file ComponentTcad2d.cc.

965 {
966
967 if (i < 0 || i >= nRegions) {
968 std::cerr << m_className << "::SetMedium:\n";
969 std::cerr << " Region " << i << " does not exist.\n";
970 return;
971 }
972
973 if (medium == 0) {
974 std::cerr << m_className << "::SetMedium:\n";
975 std::cerr << " Medium pointer is null.\n";
976 return;
977 }
978
979 regions[i].medium = medium;
980}

◆ SetRangeZ()

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

Definition at line 881 of file ComponentTcad2d.cc.

881 {
882
883 if (fabs(zmax - zmin) <= 0.) {
884 std::cerr << m_className << "::SetRangeZ:\n";
885 std::cerr << " Zero range is not permitted.\n";
886 return;
887 }
888 zMinBoundingBox = std::min(zmin, zmax);
889 zMaxBoundingBox = std::max(zmin, zmax);
890 hasRangeZ = true;
891}

◆ UnsetDriftRegion()

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

Definition at line 955 of file ComponentTcad2d.cc.

955 {
956
957 if (i < 0 || i >= nRegions) {
958 std::cerr << m_className << "::UnsetDriftRegion:\n";
959 std::cerr << " Region " << i << " does not exist.\n";
960 return;
961 }
962 regions[i].drift = false;
963}

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