19 hasElectronMobility(false),
20 hasHoleMobility(false),
30 vertices.reserve(1000);
32 elements.reserve(1000);
34 for (
int i = nMaxVertices; i--;) w[i] = 0.;
38 const double zin,
double& ex,
double& ey,
39 double& ez,
double& p,
Medium*& m,
46 std::cerr <<
" Field map is not available for interpolation.\n";
51 double x = xin, y = yin, z = zin;
53 bool xMirrored =
false;
54 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
56 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
57 if (x < xMinBoundingBox) x += cellsx;
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;
68 bool yMirrored =
false;
69 const double cellsy = yMaxBoundingBox - yMinBoundingBox;
71 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
72 if (y < yMinBoundingBox) y += cellsy;
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;
85 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
86 y > yMaxBoundingBox) {
91 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
98 ex = ey = ez = p = 0.;
103 switch (elements[i].type) {
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;
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;
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;
160 std::cerr <<
" Unknown element type (" << elements[i].type <<
").\n";
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) {
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;
183 m = regions[elements[i].region].medium;
184 if (!regions[elements[i].region].drift || m == 0) status = -5;
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;
202 m = regions[elements[i].region].medium;
203 if (!regions[elements[i].region].drift || m == 0) status = -5;
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;
224 m = regions[elements[i].region].medium;
225 if (!regions[elements[i].region].drift || m == 0) status = -5;
231 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
240 for (i = nElements; i--;) {
241 if (x < vertices[elements[i].vertex[0]].x)
continue;
242 switch (elements[i].type) {
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;
254 m = regions[elements[i].region].medium;
255 if (!regions[elements[i].region].drift || m == 0) status = -5;
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;
273 m = regions[elements[i].region].medium;
274 if (!regions[elements[i].region].drift || m == 0) status = -5;
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;
295 m = regions[elements[i].region].medium;
296 if (!regions[elements[i].region].drift || m == 0) status = -5;
302 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
311 std::cerr <<
" Point (" << x <<
", " << y <<
") is outside the mesh.\n";
318 const double z,
double& ex,
double& ey,
319 double& ez,
Medium*& m,
int& status) {
331 std::cerr <<
" Field map not available for interpolation.\n";
335 double x = xin, y = yin, z = zin;
337 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
339 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
340 if (x < xMinBoundingBox) x += cellsx;
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;
350 const double cellsy = yMaxBoundingBox - yMinBoundingBox;
352 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
353 if (y < yMinBoundingBox) y += cellsy;
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;
365 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
366 y > yMaxBoundingBox) {
370 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
377 switch (elements[i].type) {
379 if (CheckLine(x, y, i)) {
380 return regions[elements[i].region].medium;
384 if (CheckTriangle(x, y, i)) {
385 return regions[elements[i].region].medium;
389 if (CheckRectangle(x, y, i)) {
390 return regions[elements[i].region].medium;
395 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
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) {
407 if (CheckLine(x, y, i)) {
409 return regions[elements[i].region].medium;
413 if (CheckTriangle(x, y, i)) {
415 return regions[elements[i].region].medium;
419 if (CheckRectangle(x, y, i)) {
421 return regions[elements[i].region].medium;
426 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
434 for (i = nElements; i--;) {
435 if (x < vertices[elements[i].vertex[0]].x)
continue;
436 switch (elements[i].type) {
438 if (CheckLine(x, y, i)) {
440 return regions[elements[i].region].medium;
444 if (CheckTriangle(x, y, i)) {
446 return regions[elements[i].region].medium;
450 if (CheckRectangle(x, y, i)) {
452 return regions[elements[i].region].medium;
457 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
467 const double zin,
double& emob,
474 std::cerr <<
" Field map is not available for interpolation.\n";
478 double x = xin, y = yin, z = zin;
480 const double cellsx = xMaxBoundingBox - xMinBoundingBox;
482 x = xMinBoundingBox + fmod(x - xMinBoundingBox, cellsx);
483 if (x < xMinBoundingBox) x += cellsx;
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;
493 const double cellsy = xMaxBoundingBox - xMinBoundingBox;
495 y = yMinBoundingBox + fmod(y - yMinBoundingBox, cellsy);
496 if (y < yMinBoundingBox) y += cellsy;
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;
508 if (x < xMinBoundingBox || x > xMaxBoundingBox || y < yMinBoundingBox ||
509 y > yMaxBoundingBox) {
513 if (z < zMinBoundingBox || z > zMaxBoundingBox) {
520 switch (elements[i].type) {
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;
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;
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;
556 std::cerr <<
" Unknown element type (" << elements[i].type <<
").\n";
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) {
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;
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;
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;
605 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
613 for (i = nElements; i--;) {
614 if (x < vertices[elements[i].vertex[0]].x)
continue;
615 switch (elements[i].type) {
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;
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;
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;
654 std::cerr <<
" Invalid element type (" << elements[i].type <<
").\n";
662 std::cerr <<
" Point (" << x <<
", " << y <<
") is outside the mesh.\n";
668 const std::string datafilename) {
672 if (!LoadGrid(gridfilename)) {
674 std::cerr <<
" Importing mesh data failed.\n";
678 hasPotential = hasField =
false;
679 hasElectronMobility = hasHoleMobility =
false;
682 if (!LoadData(datafilename)) {
684 std::cerr <<
" Importing electric field and potential failed.\n";
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;
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;
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;
713 std::cout <<
" Available data:\n";
715 std::cout <<
" Electrostatic potential\n";
718 std::cout <<
" Electric field\n";
720 if (hasElectronMobility) {
721 std::cout <<
" Electron mobility\n";
723 if (hasHoleMobility) {
724 std::cout <<
" Hole mobility\n";
726 std::cout <<
" Bounding box:\n";
727 std::cout <<
" " << xMinBoundingBox <<
" < x [cm] < " << xMaxBoundingBox
729 std::cout <<
" " << yMinBoundingBox <<
" < y [cm] < " << yMaxBoundingBox
731 std::cout <<
" Voltage range:\n";
732 std::cout <<
" " << pMin <<
" < V < " << pMax <<
"\n";
737 std::vector<int> nElementsRegion;
738 nElementsRegion.resize(nRegions);
739 for (
int i = nRegions; i--;) nElementsRegion[i] = 0;
745 int nOtherShapes = 0;
749 std::vector<int> looseElements;
750 looseElements.clear();
754 std::vector<int> degenerateElements;
755 degenerateElements.clear();
757 for (
int i = nElements; i--;) {
758 if (elements[i].type == 1) {
760 if (elements[i].vertex[0] == elements[i].vertex[1]) {
761 degenerateElements.push_back(i);
764 }
else if (elements[i].type == 2) {
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);
772 }
else if (elements[i].type == 3) {
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);
787 if (elements[i].region >= 0 && elements[i].region < nRegions) {
788 ++nElementsRegion[elements[i].region];
790 looseElements.push_back(i);
795 if (nDegenerate > 0) {
797 std::cerr <<
" The following elements are degenerate:\n";
798 for (
int i = nDegenerate; i--;) {
799 std::cerr <<
" " << degenerateElements[i] <<
"\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";
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";
820 std::cout <<
" Number of elements: " << nElements <<
"\n";
822 std::cout <<
" " << nLines <<
" lines\n";
824 if (nTriangles > 0) {
825 std::cout <<
" " << nTriangles <<
" triangles\n";
827 if (nRectangles > 0) {
828 std::cout <<
" " << nRectangles <<
" rectangles\n";
830 if (nOtherShapes > 0) {
831 std::cout <<
" " << nOtherShapes <<
" elements of unknown type\n";
832 std::cout <<
" Program bug!\n";
838 std::cout <<
" Number of vertices: " << nVertices <<
"\n";
855 double& xmax,
double& ymax,
double& zmax) {
857 if (!
ready)
return false;
862 xmin = xMinBoundingBox;
863 xmax = xMaxBoundingBox;
870 ymin = yMinBoundingBox;
871 ymax = yMaxBoundingBox;
875 zmin = zMinBoundingBox;
876 zmax = zMaxBoundingBox;
883 if (
fabs(zmax - zmin) <= 0.) {
885 std::cerr <<
" Zero range is not permitted.\n";
888 zMinBoundingBox = std::min(zmin, zmax);
889 zMaxBoundingBox = std::max(zmin, zmax);
895 if (!
ready)
return false;
906 std::cerr <<
" Field map not yet initialised.\n";
912 std::cerr <<
" No regions are currently defined.\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 ";
924 std::cout <<
" " << regions[i].medium->GetName();
926 if (regions[i].drift) {
927 std::cout <<
" (active region)\n";
936 if (i < 0 || i >= nRegions) {
938 std::cerr <<
" Region " << i <<
" does not exist.\n";
941 name = regions[i].name;
942 active = regions[i].drift;
947 if (i < 0 || i >= nRegions) {
949 std::cerr <<
" Region " << i <<
" does not exist.\n";
952 regions[i].drift =
true;
957 if (i < 0 || i >= nRegions) {
958 std::cerr <<
m_className <<
"::UnsetDriftRegion:\n";
959 std::cerr <<
" Region " << i <<
" does not exist.\n";
962 regions[i].drift =
false;
967 if (i < 0 || i >= nRegions) {
969 std::cerr <<
" Region " << i <<
" does not exist.\n";
975 std::cerr <<
" Medium pointer is null.\n";
979 regions[i].medium = medium;
984 if (i >= (
unsigned int)nRegions) {
986 std::cerr <<
" Region " << i <<
" does not exist.\n";
990 return regions[i].medium;
994 double& dmax,
int& type) {
996 if (i < 0 || i >= nElements) {
998 std::cerr <<
" Element index (" << i <<
") out of range.\n";
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,
1007 pow(vertices[elements[i].vertex[1]].y -
1008 vertices[elements[i].vertex[0]].y,
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)) /
1021 const double a =
sqrt(
pow(vertices[elements[i].vertex[1]].x -
1022 vertices[elements[i].vertex[0]].x,
1024 pow(vertices[elements[i].vertex[1]].y -
1025 vertices[elements[i].vertex[0]].y,
1027 const double b =
sqrt(
pow(vertices[elements[i].vertex[2]].x -
1028 vertices[elements[i].vertex[0]].x,
1030 pow(vertices[elements[i].vertex[2]].y -
1031 vertices[elements[i].vertex[0]].y,
1033 const double c =
sqrt(
pow(vertices[elements[i].vertex[1]].x -
1034 vertices[elements[i].vertex[2]].x,
1036 pow(vertices[elements[i].vertex[1]].y -
1037 vertices[elements[i].vertex[2]].y,
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,
1048 pow(vertices[elements[i].vertex[1]].y -
1049 vertices[elements[i].vertex[0]].y,
1051 const double b =
sqrt(
pow(vertices[elements[i].vertex[3]].x -
1052 vertices[elements[i].vertex[0]].x,
1054 pow(vertices[elements[i].vertex[3]].y -
1055 vertices[elements[i].vertex[0]].y,
1058 dmin = std::min(a, b);
1059 dmax =
sqrt(a * a + b * b);
1062 std::cerr <<
" Unexpected element type (" << type <<
")\n";
1069 double& dmax,
int& type,
int& node1,
1070 int& node2,
int& node3,
int& node4,
int& reg) {
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;
1082 double& ex,
double& ey) {
1084 if (i < 0 || i >= nVertices) {
1086 std::cerr <<
" Node index (" << i <<
") out of range.\n";
1093 ex = vertices[i].ex;
1094 ey = vertices[i].ey;
1098bool ComponentTcad2d::LoadData(
const std::string datafilename) {
1100 std::ifstream datafile;
1101 datafile.open(datafilename.c_str(), std::ios::in);
1104 std::cerr <<
" Could not open file " << datafilename <<
".\n";
1109 std::istringstream data;
1111 std::vector<bool> isInRegion(nVertices);
1112 std::vector<int> fillCount(nVertices);
1114 for (
int i = nVertices; i--;) {
1117 vertices[i].ex = 0.;
1118 vertices[i].ey = 0.;
1119 vertices[i].emob = 0.;
1120 vertices[i].hmob = 0.;
1121 vertices[i].isShared =
false;
1124 std::string::size_type pBra, pKet, pEq;
1126 while (!datafile.fail()) {
1128 std::getline(datafile, line);
1130 line.erase(line.begin(),
1131 std::find_if(line.begin(), line.end(),
1132 not1(std::ptr_fun<int, int>(isspace))));
1134 if (line.substr(0, 8) ==
"function") {
1136 pEq = line.find(
'=');
1137 if (pEq == std::string::npos) {
1140 std::cerr <<
" Error reading file " << datafilename <<
".\n";
1141 std::cerr <<
" Line:\n";
1142 std::cerr <<
" " << line <<
"\n";
1147 line = line.substr(pEq + 1);
1148 std::string dataset;
1152 if (dataset ==
"ElectrostaticPotential") {
1153 std::getline(datafile, line);
1154 std::getline(datafile, line);
1155 std::getline(datafile, line);
1156 std::getline(datafile, line);
1158 pBra = line.find(
'[');
1159 pKet = line.find(
']');
1160 if (pKet < pBra || pBra == std::string::npos ||
1161 pKet == std::string::npos) {
1163 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1164 std::cerr <<
" Line:\n";
1165 std::cerr <<
" " << line <<
"\n";
1170 line = line.substr(pBra + 1, pKet - pBra - 1);
1177 for (
int j = 0; j < nRegions; ++j) {
1178 if (name == regions[j].name) {
1185 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1186 std::cerr <<
" Unknown region " << name <<
".\n";
1190 std::getline(datafile, line);
1191 pBra = line.find(
'(');
1192 pKet = line.find(
')');
1193 if (pKet < pBra || pBra == std::string::npos ||
1194 pKet == std::string::npos) {
1196 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1197 std::cerr <<
" Line:\n";
1198 std::cerr <<
" " << line <<
"\n";
1203 line = line.substr(pBra + 1, pKet - pBra - 1);
1209 for (
int j = nVertices; j--;) isInRegion[j] =
false;
1210 for (
int j = 0; j < nElements; ++j) {
1211 if (elements[j].region != index)
continue;
1212 for (
int k = 0; k <= elements[j].type; ++k) {
1213 isInRegion[elements[j].vertex[k]] =
true;
1218 for (
int j = 0; j < nValues; ++j) {
1222 while (ivertex < nVertices) {
1223 if (isInRegion[ivertex])
break;
1228 if (ivertex >= nVertices) {
1230 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1231 std::cerr <<
" Dataset ElectrostaticPotential:\n";
1232 std::cerr <<
" More values than vertices in region " << name
1238 vertices[ivertex].p = val;
1239 ++fillCount[ivertex];
1242 hasPotential =
true;
1243 }
else if (dataset ==
"ElectricField") {
1245 std::getline(datafile, line);
1246 std::getline(datafile, line);
1247 std::getline(datafile, line);
1248 std::getline(datafile, line);
1249 pBra = line.find(
'[');
1250 pKet = line.find(
']');
1251 if (pKet < pBra || pBra == std::string::npos ||
1252 pKet == std::string::npos) {
1254 std::cerr <<
" Error reading file " << datafilename <<
".\n";
1255 std::cerr <<
" Line:\n";
1256 std::cerr <<
" " << line <<
"\n";
1261 line = line.substr(pBra + 1, pKet - pBra - 1);
1267 for (
int j = 0; j < nRegions; ++j) {
1268 if (name == regions[j].name) {
1275 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1276 std::cerr <<
" Unknown region " << name <<
".\n";
1279 std::getline(datafile, line);
1280 pBra = line.find(
'(');
1281 pKet = line.find(
')');
1282 if (pKet < pBra || pBra == std::string::npos ||
1283 pKet == std::string::npos) {
1285 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1286 std::cerr <<
" Line:\n";
1287 std::cerr <<
" " << line <<
"\n";
1292 line = line.substr(pBra + 1, pKet - pBra - 1);
1298 nValues = nValues / 2;
1299 for (
int j = nVertices; j--;) isInRegion[j] =
false;
1300 for (
int j = 0; j < nElements; ++j) {
1301 if (elements[j].region != index)
continue;
1302 for (
int k = 0; k <= elements[j].type; ++k) {
1303 isInRegion[elements[j].vertex[k]] =
true;
1308 for (
int j = 0; j < nValues; ++j) {
1309 datafile >> val1 >> val2;
1310 while (ivertex < nVertices) {
1311 if (isInRegion[ivertex])
break;
1314 if (ivertex >= nVertices) {
1316 <<
" Error reading file " << datafilename <<
"\n";
1317 std::cerr <<
" Dataset ElectricField:\n";
1318 std::cerr <<
" More values than vertices in region " << name
1324 vertices[ivertex].ex = val1;
1325 vertices[ivertex].ey = val2;
1329 }
else if (dataset ==
"eMobility") {
1330 std::getline(datafile, line);
1331 std::getline(datafile, line);
1332 std::getline(datafile, line);
1333 std::getline(datafile, line);
1335 pBra = line.find(
'[');
1336 pKet = line.find(
']');
1337 if (pKet < pBra || pBra == std::string::npos ||
1338 pKet == std::string::npos) {
1340 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1341 std::cerr <<
" Line:\n";
1342 std::cerr <<
" " << line <<
"\n";
1347 line = line.substr(pBra + 1, pKet - pBra - 1);
1354 for (
int j = 0; j < nRegions; ++j) {
1355 if (name == regions[j].name) {
1362 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1363 std::cerr <<
" Unknown region " << name <<
".\n";
1367 std::getline(datafile, line);
1368 pBra = line.find(
'(');
1369 pKet = line.find(
')');
1370 if (pKet < pBra || pBra == std::string::npos ||
1371 pKet == std::string::npos) {
1373 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1374 std::cerr <<
" Line:\n";
1375 std::cerr <<
" " << line <<
"\n";
1380 line = line.substr(pBra + 1, pKet - pBra - 1);
1386 for (
int j = nVertices; j--;) isInRegion[j] =
false;
1387 for (
int j = 0; j < nElements; ++j) {
1388 if (elements[j].region != index)
continue;
1389 for (
int k = 0; k <= elements[j].type; ++k) {
1390 isInRegion[elements[j].vertex[k]] =
true;
1395 for (
int j = 0; j < nValues; ++j) {
1399 while (ivertex < nVertices) {
1400 if (isInRegion[ivertex])
break;
1405 if (ivertex >= nVertices) {
1407 std::cerr <<
" Dataset eMobility:\n";
1408 std::cerr <<
" More values than vertices in region " << name
1415 vertices[ivertex].emob = val * 1.e-9;
1416 ++fillCount[ivertex];
1419 hasElectronMobility =
true;
1420 }
else if (dataset ==
"hMobility") {
1421 std::getline(datafile, line);
1422 std::getline(datafile, line);
1423 std::getline(datafile, line);
1424 std::getline(datafile, line);
1426 pBra = line.find(
'[');
1427 pKet = line.find(
']');
1428 if (pKet < pBra || pBra == std::string::npos ||
1429 pKet == std::string::npos) {
1431 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1432 std::cerr <<
" Line:\n";
1433 std::cerr <<
" " << line <<
"\n";
1438 line = line.substr(pBra + 1, pKet - pBra - 1);
1445 for (
int j = 0; j < nRegions; ++j) {
1446 if (name == regions[j].name) {
1453 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1454 std::cerr <<
" Unknown region " << name <<
".\n";
1458 std::getline(datafile, line);
1459 pBra = line.find(
'(');
1460 pKet = line.find(
')');
1461 if (pKet < pBra || pBra == std::string::npos ||
1462 pKet == std::string::npos) {
1464 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1465 std::cerr <<
" Line:\n";
1466 std::cerr <<
" " << line <<
"\n";
1471 line = line.substr(pBra + 1, pKet - pBra - 1);
1477 for (
int j = nVertices; j--;) isInRegion[j] =
false;
1478 for (
int j = 0; j < nElements; ++j) {
1479 if (elements[j].region != index)
continue;
1480 for (
int k = 0; k <= elements[j].type; ++k) {
1481 isInRegion[elements[j].vertex[k]] =
true;
1486 for (
int j = 0; j < nValues; ++j) {
1490 while (ivertex < nVertices) {
1491 if (isInRegion[ivertex])
break;
1496 if (ivertex >= nVertices) {
1498 std::cerr <<
" Dataset hMobility:\n";
1499 std::cerr <<
" More values than vertices in region " << name
1506 vertices[ivertex].hmob = val * 1.e-9;
1507 ++fillCount[ivertex];
1510 hasHoleMobility =
true;
1514 if (datafile.fail() && !datafile.eof()) {
1516 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1522 for (
int i = nVertices; i--;) {
1523 if (fillCount[i] > 1) vertices[i].isShared =
true;
1531bool ComponentTcad2d::LoadGrid(
const std::string gridfilename) {
1534 std::ifstream gridfile;
1535 gridfile.open(gridfilename.c_str(), std::ios::in);
1538 std::cerr <<
" Could not open file " << gridfilename <<
".\n";
1543 std::istringstream data;
1547 std::string::size_type pBra, pKet, pEq;
1552 while (!gridfile.fail()) {
1554 std::getline(gridfile, line);
1557 line.erase(line.begin(), find_if(line.begin(), line.end(),
1558 not1(std::ptr_fun<int, int>(isspace))));
1560 if (line.substr(0, 10) ==
"nb_regions") {
1561 pEq = line.find(
'=');
1562 if (pEq == std::string::npos) {
1565 std::cerr <<
" Could not read number of regions.\n";
1570 line = line.substr(pEq + 1);
1576 if (gridfile.fail())
break;
1578 if (gridfile.eof()) {
1581 std::cerr <<
" Could not find entry 'nb_regions' in file\n";
1582 std::cerr <<
" " << gridfilename <<
".\n";
1586 }
else if (gridfile.fail()) {
1589 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1595 regions.resize(nRegions);
1596 for (
int j = nRegions; j--;) {
1597 regions[j].name =
"";
1598 regions[j].drift =
false;
1599 regions[j].medium = 0;
1604 std::cout <<
" Found " << nRegions <<
" regions.\n";
1608 while (!gridfile.fail()) {
1609 std::getline(gridfile, line);
1611 line.erase(line.begin(), find_if(line.begin(), line.end(),
1612 not1(std::ptr_fun<int, int>(isspace))));
1614 if (line.substr(0, 7) ==
"regions") {
1616 pBra = line.find(
'[');
1617 pKet = line.find(
']');
1618 if (pKet < pBra || pBra == std::string::npos ||
1619 pKet == std::string::npos) {
1622 std::cerr <<
" Could not read region names.\n";
1627 line = line.substr(pBra + 1, pKet - pBra - 1);
1629 for (
int j = 0; j < nRegions; ++j) {
1630 data >> regions[j].name;
1633 regions[j].drift =
true;
1634 regions[j].medium = 0;
1639 if (gridfile.eof()) {
1642 std::cerr <<
" Could not find entry 'regions' in file\n";
1643 std::cerr <<
" " << gridfilename <<
".\n";
1647 }
else if (gridfile.fail()) {
1650 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1658 while (!gridfile.fail()) {
1659 std::getline(gridfile, line);
1661 line.erase(line.begin(), find_if(line.begin(), line.end(),
1662 not1(std::ptr_fun<int, int>(isspace))));
1664 if (line.substr(0, 8) ==
"Vertices") {
1666 pBra = line.find(
'(');
1667 pKet = line.find(
')');
1668 if (pKet < pBra || pBra == std::string::npos ||
1669 pKet == std::string::npos) {
1672 std::cerr <<
" Could not read number of vertices.\n";
1677 line = line.substr(pBra + 1, pKet - pBra - 1);
1681 vertices.resize(nVertices);
1683 for (
int j = 0; j < nVertices; ++j) {
1684 gridfile >> vertices[j].x >> vertices[j].y;
1686 vertices[j].x *= 1.e-4;
1687 vertices[j].y *= 1.e-4;
1693 if (gridfile.eof()) {
1695 std::cerr <<
" Could not find section 'Vertices' in file\n";
1696 std::cerr <<
" " << gridfilename <<
".\n";
1700 }
else if (gridfile.fail()) {
1702 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1712 std::vector<int> edgeP1;
1714 std::vector<int> edgeP2;
1716 while (!gridfile.fail()) {
1717 std::getline(gridfile, line);
1719 line.erase(line.begin(), find_if(line.begin(), line.end(),
1720 not1(std::ptr_fun<int, int>(isspace))));
1722 if (line.substr(0, 5) ==
"Edges") {
1724 pBra = line.find(
'(');
1725 pKet = line.find(
')');
1726 if (pKet < pBra || pBra == std::string::npos ||
1727 pKet == std::string::npos) {
1730 std::cerr <<
" Could not read number of edges.\n";
1735 line = line.substr(pBra + 1, pKet - pBra - 1);
1739 edgeP1.resize(nEdges);
1740 edgeP2.resize(nEdges);
1742 for (
int j = 0; j < nEdges; ++j) {
1743 gridfile >> edgeP1[j] >> edgeP2[j];
1749 if (gridfile.eof()) {
1751 std::cerr <<
" Could not find section 'Edges' in file\n";
1752 std::cerr <<
" " << gridfilename <<
".\n";
1756 }
else if (gridfile.fail()) {
1758 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1765 for (
int i = nEdges; i--;) {
1767 if (edgeP1[i] < 0 || edgeP1[i] >= nVertices || edgeP2[i] < 0 ||
1768 edgeP2[i] >= nVertices) {
1770 std::cerr <<
" Vertex index of edge " << i <<
" out of range.\n";
1776 if (edgeP1[i] == edgeP2[i]) {
1778 std::cerr <<
" Edge " << i <<
" is degenerate.\n";
1786 int edge0, edge1, edge2, edge3;
1788 while (!gridfile.fail()) {
1789 std::getline(gridfile, line);
1791 line.erase(line.begin(), find_if(line.begin(), line.end(),
1792 not1(std::ptr_fun<int, int>(isspace))));
1794 if (line.substr(0, 8) ==
"Elements") {
1796 pBra = line.find(
'(');
1797 pKet = line.find(
')');
1798 if (pKet < pBra || pBra == std::string::npos ||
1799 pKet == std::string::npos) {
1802 std::cerr <<
" Could not read number of elements.\n";
1807 line = line.substr(pBra + 1, pKet - pBra - 1);
1812 elements.resize(nElements);
1814 for (
int j = 0; j < nElements; ++j) {
1815 for (
int k = nMaxVertices; k--;) elements[j].vertex[k] = -1;
1816 elements[j].nNeighbours = 0;
1817 elements[j].neighbours.clear();
1823 gridfile >> edge0 >> edge1;
1824 if (edge0 < 0) edge0 = -edge0 - 1;
1825 if (edge1 < 0) edge1 = -edge1 - 1;
1827 if (edge0 >= nEdges || edge1 >= nEdges) {
1829 std::cerr <<
" Error reading file " << gridfilename
1830 <<
" (line " << iLine <<
").\n";
1831 std::cerr <<
" Edge index out of range.\n";
1841 if (vertices[edgeP1[edge0]].x > vertices[edgeP2[edge0]].x) {
1842 elements[j].vertex[0] = edgeP2[edge0];
1843 elements[j].vertex[1] = edgeP1[edge0];
1845 elements[j].vertex[0] = edgeP1[edge0];
1846 elements[j].vertex[1] = edgeP2[edge0];
1851 gridfile >> edge0 >> edge1 >> edge2;
1853 if (edge0 < 0) edge0 = -edge0 - 1;
1854 if (edge1 < 0) edge1 = -edge1 - 1;
1855 if (edge2 < 0) edge2 = -edge2 - 1;
1856 if (edge0 >= nEdges || edge1 >= nEdges || edge2 >= nEdges) {
1858 std::cerr <<
" Error reading file " << gridfilename
1859 <<
" (line " << iLine <<
").\n";
1860 std::cerr <<
" Edge index out of range.\n";
1865 elements[j].vertex[0] = edgeP1[edge0];
1866 elements[j].vertex[1] = edgeP2[edge0];
1867 if (edgeP1[edge1] != elements[j].vertex[0] &&
1868 edgeP1[edge1] != elements[j].vertex[1]) {
1869 elements[j].vertex[2] = edgeP1[edge1];
1871 elements[j].vertex[2] = edgeP2[edge1];
1874 while (vertices[elements[j].vertex[0]].x >
1875 vertices[elements[j].vertex[1]].x ||
1876 vertices[elements[j].vertex[0]].x >
1877 vertices[elements[j].vertex[2]].x) {
1878 const int tmp = elements[j].vertex[0];
1879 elements[j].vertex[0] = elements[j].vertex[1];
1880 elements[j].vertex[1] = elements[j].vertex[2];
1881 elements[j].vertex[2] = tmp;
1886 gridfile >> edge0 >> edge1 >> edge2 >> edge3;
1888 if (edge0 >= nEdges || -edge0 - 1 >= nEdges || edge1 >= nEdges ||
1889 -edge1 - 1 >= nEdges || edge2 >= nEdges ||
1890 -edge2 - 1 >= nEdges || edge3 >= nEdges ||
1891 -edge3 - 1 >= nEdges) {
1893 std::cerr <<
" Error reading file " << gridfilename
1894 <<
" (line " << iLine <<
").\n";
1895 std::cerr <<
" Edge index out of range.\n";
1901 elements[j].vertex[0] = edgeP1[edge0];
1903 elements[j].vertex[0] = edgeP2[-edge0 - 1];
1905 elements[j].vertex[1] = edgeP1[edge1];
1907 elements[j].vertex[1] = edgeP2[-edge1 - 1];
1909 elements[j].vertex[2] = edgeP1[edge2];
1911 elements[j].vertex[2] = edgeP2[-edge2 - 1];
1913 elements[j].vertex[3] = edgeP1[edge3];
1915 elements[j].vertex[3] = edgeP2[-edge3 - 1];
1918 while (vertices[elements[j].vertex[0]].x >
1919 vertices[elements[j].vertex[1]].x ||
1920 vertices[elements[j].vertex[0]].x >
1921 vertices[elements[j].vertex[2]].x ||
1922 vertices[elements[j].vertex[0]].x >
1923 vertices[elements[j].vertex[3]].x) {
1924 const int tmp = elements[j].vertex[0];
1925 elements[j].vertex[0] = elements[j].vertex[1];
1926 elements[j].vertex[1] = elements[j].vertex[2];
1927 elements[j].vertex[2] = elements[j].vertex[3];
1928 elements[j].vertex[3] = tmp;
1934 <<
" Error reading file " << gridfilename <<
" (line "
1936 std::cerr <<
" Invalid element type (" << type
1937 <<
") for 2d mesh.\n";
1943 elements[j].type = type;
1944 elements[j].region = -1;
1949 if (gridfile.eof()) {
1951 std::cerr <<
" Could not find section 'Elements' in file\n";
1952 std::cerr <<
" " << gridfilename <<
".\n";
1956 }
else if (gridfile.fail()) {
1958 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1967 while (!gridfile.fail()) {
1968 std::getline(gridfile, line);
1969 line.erase(line.begin(), find_if(line.begin(), line.end(),
1970 not1(std::ptr_fun<int, int>(isspace))));
1972 if (line.substr(0, 6) ==
"Region") {
1974 pBra = line.find(
'(');
1975 pKet = line.find(
')');
1976 if (pKet < pBra || pBra == std::string::npos ||
1977 pKet == std::string::npos) {
1979 std::cerr <<
" Could not read region name.\n";
1984 line = line.substr(pBra + 1, pKet - pBra - 1);
1989 for (
int j = 0; j < nRegions; ++j) {
1990 if (name == regions[j].name) {
1998 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
1999 std::cerr <<
" Unknown region " << name <<
".\n";
2002 std::getline(gridfile, line);
2003 std::getline(gridfile, line);
2004 pBra = line.find(
'(');
2005 pKet = line.find(
')');
2006 if (pKet < pBra || pBra == std::string::npos ||
2007 pKet == std::string::npos) {
2010 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
2011 std::cerr <<
" Could not read number of elements in region " << name
2017 line = line.substr(pBra + 1, pKet - pBra - 1);
2018 int nElementsRegion;
2021 data >> nElementsRegion;
2023 for (
int j = 0; j < nElementsRegion; ++j) {
2024 gridfile >> iElement;
2025 elements[iElement].region = index;
2031 if (gridfile.fail() && !gridfile.eof()) {
2033 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
2041void ComponentTcad2d::FindNeighbours() {
2043 std::vector<std::vector<bool> > adjacent;
2044 adjacent.resize(nElements);
2045 for (
int i = nElements; i--;) {
2046 adjacent[i].resize(nElements);
2047 for (
int j = nElements; j--;) {
2048 adjacent[i][j] =
false;
2052 for (
int i = nElements; i--;) {
2053 for (
int m = nMaxVertices; m--;) {
2054 if (elements[i].vertex[m] < 0)
continue;
2055 for (
int j = nElements; j--;) {
2056 if (i == j || adjacent[i][j])
continue;
2057 for (
int n = nMaxVertices; n--;) {
2058 if (elements[i].vertex[m] == elements[j].vertex[n]) {
2059 adjacent[i][j] =
true;
2067 for (
int i = nElements; i--;) {
2068 elements[i].nNeighbours = 0;
2069 elements[i].neighbours.clear();
2070 for (
int j = nElements; j--;) {
2071 if (adjacent[i][j]) {
2072 elements[i].neighbours.push_back(j);
2073 elements[i].nNeighbours += 1;
2079void ComponentTcad2d::Cleanup() {
2094bool ComponentTcad2d::CheckRectangle(
const double x,
const double y,
2097 if (y < vertices[elements[i].vertex[0]].y ||
2098 x > vertices[elements[i].vertex[3]].x ||
2099 y > vertices[elements[i].vertex[1]].y) {
2105 (x - 0.5 * (vertices[elements[i].vertex[0]].x +
2106 vertices[elements[i].vertex[3]].x)) /
2107 (vertices[elements[i].vertex[3]].x - vertices[elements[i].vertex[0]].x);
2109 (y - 0.5 * (vertices[elements[i].vertex[0]].y +
2110 vertices[elements[i].vertex[1]].y)) /
2111 (vertices[elements[i].vertex[1]].y - vertices[elements[i].vertex[0]].y);
2113 w[0] = (0.5 - u) * (0.5 - v);
2114 w[1] = (0.5 - u) * (0.5 + v);
2115 w[2] = (0.5 + u) * (0.5 + v);
2116 w[3] = (0.5 + u) * (0.5 - v);
2121bool ComponentTcad2d::CheckTriangle(
const double x,
const double y,
2124 if (x > vertices[elements[i].vertex[1]].x &&
2125 x > vertices[elements[i].vertex[2]].x)
2127 if (y < vertices[elements[i].vertex[0]].y &&
2128 y < vertices[elements[i].vertex[1]].y &&
2129 y < vertices[elements[i].vertex[2]].y)
2131 if (y > vertices[elements[i].vertex[0]].y &&
2132 y > vertices[elements[i].vertex[1]].y &&
2133 y > vertices[elements[i].vertex[2]].y)
2141 vertices[elements[i].vertex[1]].x - vertices[elements[i].vertex[0]].x;
2143 vertices[elements[i].vertex[1]].y - vertices[elements[i].vertex[0]].y;
2145 vertices[elements[i].vertex[2]].x - vertices[elements[i].vertex[0]].x;
2147 vertices[elements[i].vertex[2]].y - vertices[elements[i].vertex[0]].y;
2149 w[1] = ((x - vertices[elements[i].vertex[0]].x) * v2y -
2150 (y - vertices[elements[i].vertex[0]].y) * v2x) /
2151 (v1x * v2y - v1y * v2x);
2152 if (w[1] < 0. || w[1] > 1.)
return false;
2154 w[2] = ((vertices[elements[i].vertex[0]].x - x) * v1y -
2155 (vertices[elements[i].vertex[0]].y - y) * v1x) /
2156 (v1x * v2y - v1y * v2x);
2157 if (w[2] < 0. || w[1] + w[2] > 1.)
return false;
2160 w[0] = 1. - w[1] - w[2];
2165bool ComponentTcad2d::CheckLine(
const double x,
const double y,
const int i) {
2167 if (x > vertices[elements[i].vertex[1]].x)
return false;
2168 if (y < vertices[elements[i].vertex[0]].y &&
2169 y < vertices[elements[i].vertex[1]].y)
2171 if (y > vertices[elements[i].vertex[0]].y &&
2172 y > vertices[elements[i].vertex[1]].y)
2175 vertices[elements[i].vertex[1]].x - vertices[elements[i].vertex[0]].x;
2177 vertices[elements[i].vertex[1]].y - vertices[elements[i].vertex[0]].y;
2178 const double tx = (x - vertices[elements[i].vertex[0]].x) / v1x;
2179 if (tx < 0. || tx > 1.)
return false;
2180 const double ty = (y - vertices[elements[i].vertex[0]].y) / v1y;
2181 if (ty < 0. || ty > 1.)
return false;
2191void ComponentTcad2d::Reset() {
2198void ComponentTcad2d::UpdatePeriodicity() {
2201 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2202 std::cerr <<
" Field map not available.\n";
2208 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2209 std::cerr <<
" Both simple and mirror periodicity\n";
2210 std::cerr <<
" along x requested; reset.\n";
2215 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2216 std::cerr <<
" Both simple and mirror periodicity\n";
2217 std::cerr <<
" along y requested; reset.\n";
2222 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2223 std::cerr <<
" Periodicity along z requested; reset.\n";
2228 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2229 std::cerr <<
" Axial symmetry is not supported; reset.\n";
2234 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
2235 std::cerr <<
" Rotation symmetry is not supported; reset.\n";
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)
bool GetNode(const int i, double &x, double &y, double &v, double &ex, double &ey)
void SetDriftRegion(const int ireg)
void UnsetDriftRegion(const int ireg)
void SetMedium(const int ireg, Medium *m)
bool GetElement(const int i, double &vol, double &dmin, double &dmax, int &type)
bool GetVoltageRange(double &vmin, double &vmax)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
bool Initialise(const std::string gridfilename, const std::string datafilename)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
void SetRangeZ(const double zmin, const double zmax)
Medium * GetMedium(const double &x, const double &y, const double &z)
void GetRegion(const int i, std::string &name, bool &active)
bool GetMobility(const double x, const double y, const double z, double &emob, double &hmob)