26 for (
int i = nMaxVertices; i--;) m_w[i] = 0.;
30 const double zin,
double& ex,
double& ey,
31 double& ez,
double& p,
Medium*& m,
38 std::cerr <<
" Field map is not available for interpolation.\n";
44 ex = ey = ez = p = 0.;
46 double x = xin, y = yin, z = zin;
48 bool xMirrored =
false;
49 const double cellsx = m_xMaxBoundingBox - m_xMinBoundingBox;
51 x = m_xMinBoundingBox + fmod(x - m_xMinBoundingBox, cellsx);
52 if (x < m_xMinBoundingBox) x += cellsx;
54 double xNew = m_xMinBoundingBox + fmod(x - m_xMinBoundingBox, cellsx);
55 if (xNew < m_xMinBoundingBox) xNew += cellsx;
56 int nx = int(floor(0.5 + (xNew - x) / cellsx));
57 if (nx != 2 * (nx / 2)) {
58 xNew = m_xMinBoundingBox + m_xMaxBoundingBox - xNew;
63 bool yMirrored =
false;
64 const double cellsy = m_yMaxBoundingBox - m_yMinBoundingBox;
66 y = m_yMinBoundingBox + fmod(y - m_yMinBoundingBox, cellsy);
67 if (y < m_yMinBoundingBox) y += cellsy;
69 double yNew = m_yMinBoundingBox + fmod(y - m_yMinBoundingBox, cellsy);
70 if (yNew < m_yMinBoundingBox) yNew += cellsy;
71 int ny = int(floor(0.5 + (yNew - y) / cellsy));
72 if (ny != 2 * (ny / 2)) {
73 yNew = m_yMinBoundingBox + m_yMaxBoundingBox - yNew;
78 bool zMirrored =
false;
79 const double cellsz = m_zMaxBoundingBox - m_zMinBoundingBox;
81 z = m_zMinBoundingBox + fmod(z - m_zMinBoundingBox, cellsz);
82 if (z < m_zMinBoundingBox) z += cellsz;
84 double zNew = m_zMinBoundingBox + fmod(z - m_zMinBoundingBox, cellsz);
85 if (zNew < m_zMinBoundingBox) zNew += cellsz;
86 int nz = int(floor(0.5 + (zNew - z) / cellsz));
87 if (nz != 2 * (nz / 2)) {
88 zNew = m_zMinBoundingBox + m_zMaxBoundingBox - zNew;
95 if (x < m_xMinBoundingBox || x > m_xMaxBoundingBox || y < m_yMinBoundingBox ||
96 y > m_yMaxBoundingBox || z < m_zMinBoundingBox || z > m_zMaxBoundingBox) {
99 std::cerr <<
" Point (" << x <<
", " << y <<
", " << z
100 <<
") is outside the bounding box.\n";
109 int i = m_lastElement;
110 switch (m_elements[i].type) {
112 if (CheckTriangle(x, y, z, i)) {
113 ex = m_w[0] * m_vertices[m_elements[i].vertex[0]].ex +
114 m_w[1] * m_vertices[m_elements[i].vertex[1]].ex +
115 m_w[2] * m_vertices[m_elements[i].vertex[2]].ex;
116 ey = m_w[0] * m_vertices[m_elements[i].vertex[0]].ey +
117 m_w[1] * m_vertices[m_elements[i].vertex[1]].ey +
118 m_w[2] * m_vertices[m_elements[i].vertex[2]].ey;
119 ez = m_w[0] * m_vertices[m_elements[i].vertex[0]].ez +
120 m_w[1] * m_vertices[m_elements[i].vertex[1]].ez +
121 m_w[2] * m_vertices[m_elements[i].vertex[2]].ez;
122 p = m_w[0] * m_vertices[m_elements[i].vertex[0]].p +
123 m_w[1] * m_vertices[m_elements[i].vertex[1]].p +
124 m_w[2] * m_vertices[m_elements[i].vertex[2]].p;
125 if (xMirrored) ex = -ex;
126 if (yMirrored) ey = -ey;
127 if (zMirrored) ez = -ez;
128 m = m_regions[m_elements[i].region].medium;
129 if (!m_regions[m_elements[i].region].drift || m == 0) status = -5;
134 if (CheckTetrahedron(x, y, z, i)) {
135 ex = m_w[0] * m_vertices[m_elements[i].vertex[0]].ex +
136 m_w[1] * m_vertices[m_elements[i].vertex[1]].ex +
137 m_w[2] * m_vertices[m_elements[i].vertex[2]].ex +
138 m_w[3] * m_vertices[m_elements[i].vertex[3]].ex;
139 ey = m_w[0] * m_vertices[m_elements[i].vertex[0]].ey +
140 m_w[1] * m_vertices[m_elements[i].vertex[1]].ey +
141 m_w[2] * m_vertices[m_elements[i].vertex[2]].ey +
142 m_w[3] * m_vertices[m_elements[i].vertex[3]].ey;
143 ez = m_w[0] * m_vertices[m_elements[i].vertex[0]].ez +
144 m_w[1] * m_vertices[m_elements[i].vertex[1]].ez +
145 m_w[2] * m_vertices[m_elements[i].vertex[2]].ez +
146 m_w[3] * m_vertices[m_elements[i].vertex[3]].ez;
147 p = m_w[0] * m_vertices[m_elements[i].vertex[0]].p +
148 m_w[1] * m_vertices[m_elements[i].vertex[1]].p +
149 m_w[2] * m_vertices[m_elements[i].vertex[2]].p +
150 m_w[3] * m_vertices[m_elements[i].vertex[3]].p;
151 if (xMirrored) ex = -ex;
152 if (yMirrored) ey = -ey;
153 if (zMirrored) ez = -ez;
154 m = m_regions[m_elements[i].region].medium;
155 if (!m_regions[m_elements[i].region].drift || m == 0) status = -5;
161 std::cerr <<
" Unknown element type (" << m_elements[i].type <<
").\n";
169 for (i = m_nElements; i--;) {
170 switch (m_elements[i].type) {
172 if (CheckTriangle(x, y, z, i)) {
173 ex = m_w[0] * m_vertices[m_elements[i].vertex[0]].ex +
174 m_w[1] * m_vertices[m_elements[i].vertex[1]].ex +
175 m_w[2] * m_vertices[m_elements[i].vertex[2]].ex;
176 ey = m_w[0] * m_vertices[m_elements[i].vertex[0]].ey +
177 m_w[1] * m_vertices[m_elements[i].vertex[1]].ey +
178 m_w[2] * m_vertices[m_elements[i].vertex[2]].ey;
179 ez = m_w[0] * m_vertices[m_elements[i].vertex[0]].ez +
180 m_w[1] * m_vertices[m_elements[i].vertex[1]].ez +
181 m_w[2] * m_vertices[m_elements[i].vertex[2]].ez;
182 p = m_w[0] * m_vertices[m_elements[i].vertex[0]].p +
183 m_w[1] * m_vertices[m_elements[i].vertex[1]].p +
184 m_w[2] * m_vertices[m_elements[i].vertex[2]].p;
185 if (xMirrored) ex = -ex;
186 if (yMirrored) ey = -ey;
187 if (zMirrored) ez = -ez;
189 m = m_regions[m_elements[i].region].medium;
190 if (!m_regions[m_elements[i].region].drift || m == 0) status = -5;
195 if (CheckTetrahedron(x, y, z, i)) {
196 ex = m_w[0] * m_vertices[m_elements[i].vertex[0]].ex +
197 m_w[1] * m_vertices[m_elements[i].vertex[1]].ex +
198 m_w[2] * m_vertices[m_elements[i].vertex[2]].ex +
199 m_w[3] * m_vertices[m_elements[i].vertex[3]].ex;
200 ey = m_w[0] * m_vertices[m_elements[i].vertex[0]].ey +
201 m_w[1] * m_vertices[m_elements[i].vertex[1]].ey +
202 m_w[2] * m_vertices[m_elements[i].vertex[2]].ey +
203 m_w[3] * m_vertices[m_elements[i].vertex[3]].ey;
204 ez = m_w[0] * m_vertices[m_elements[i].vertex[0]].ez +
205 m_w[1] * m_vertices[m_elements[i].vertex[1]].ez +
206 m_w[2] * m_vertices[m_elements[i].vertex[2]].ez +
207 m_w[3] * m_vertices[m_elements[i].vertex[3]].ez;
208 p = m_w[0] * m_vertices[m_elements[i].vertex[0]].p +
209 m_w[1] * m_vertices[m_elements[i].vertex[1]].p +
210 m_w[2] * m_vertices[m_elements[i].vertex[2]].p +
211 m_w[3] * m_vertices[m_elements[i].vertex[3]].p;
212 if (xMirrored) ex = -ex;
213 if (yMirrored) ey = -ey;
214 if (zMirrored) ez = -ez;
216 m = m_regions[m_elements[i].region].medium;
217 if (!m_regions[m_elements[i].region].drift || m == 0) status = -5;
223 std::cerr <<
" Invalid element type (" << m_elements[i].type
233 std::cerr <<
" Point (" << x <<
", " << y <<
", " << z
234 <<
") is outside the mesh.\n";
241 const double z,
double& ex,
double& ey,
242 double& ez,
Medium*& m,
int& status) {
254 std::cerr <<
" Field map not available for interpolation.\n";
258 double x = xin, y = yin, z = zin;
260 const double cellsx = m_xMaxBoundingBox - m_xMinBoundingBox;
262 x = m_xMinBoundingBox + fmod(x - m_xMinBoundingBox, cellsx);
263 if (x < m_xMinBoundingBox) x += cellsx;
265 double xNew = m_xMinBoundingBox + fmod(x - m_xMinBoundingBox, cellsx);
266 if (xNew < m_xMinBoundingBox) xNew += cellsx;
267 int nx = int(floor(0.5 + (xNew - x) / cellsx));
268 if (nx != 2 * (nx / 2)) {
269 xNew = m_xMinBoundingBox + m_xMaxBoundingBox - xNew;
273 const double cellsy = m_yMaxBoundingBox - m_yMinBoundingBox;
275 y = m_yMinBoundingBox + fmod(y - m_yMinBoundingBox, cellsy);
276 if (y < m_yMinBoundingBox) y += cellsy;
278 double yNew = m_yMinBoundingBox + fmod(y - m_yMinBoundingBox, cellsy);
279 if (yNew < m_yMinBoundingBox) yNew += cellsy;
280 int ny = int(floor(0.5 + (yNew - y) / cellsy));
281 if (ny != 2 * (ny / 2)) {
282 yNew = m_yMinBoundingBox + m_yMaxBoundingBox - yNew;
286 const double cellsz = m_zMaxBoundingBox - m_zMinBoundingBox;
288 z = m_zMinBoundingBox + fmod(z - m_zMinBoundingBox, cellsz);
289 if (z < m_zMinBoundingBox) z += cellsz;
291 double zNew = m_zMinBoundingBox + fmod(z - m_zMinBoundingBox, cellsz);
292 if (zNew < m_zMinBoundingBox) zNew += cellsz;
293 int nz = int(floor(0.5 + (zNew - z) / cellsz));
294 if (nz != 2 * (nz / 2)) {
295 zNew = m_zMinBoundingBox + m_zMaxBoundingBox - zNew;
301 if (x < m_xMinBoundingBox || x > m_xMaxBoundingBox || y < m_yMinBoundingBox ||
302 y > m_yMaxBoundingBox || z < m_zMinBoundingBox || z > m_zMaxBoundingBox) {
307 int i = m_lastElement;
308 switch (m_elements[i].type) {
310 if (CheckTriangle(x, y, z, i)) {
311 return m_regions[m_elements[i].region].medium;
315 if (CheckTetrahedron(x, y, z, i)) {
316 return m_regions[m_elements[i].region].medium;
321 std::cerr <<
" Invalid element type (" << m_elements[i].type <<
").\n";
328 for (i = m_nElements; i--;) {
329 switch (m_elements[i].type) {
331 if (CheckTriangle(x, y, z, i)) {
333 return m_regions[m_elements[i].region].medium;
337 if (CheckTetrahedron(x, y, z, i)) {
339 return m_regions[m_elements[i].region].medium;
344 std::cerr <<
" Invalid element type (" << m_elements[i].type
355 const std::string datafilename) {
359 if (!LoadGrid(gridfilename)) {
361 std::cerr <<
" Importing mesh data failed.\n";
366 if (!LoadData(datafilename)) {
368 std::cerr <<
" Importing electric field and potential failed.\n";
373 m_xMaxBoundingBox = m_vertices[m_elements[0].vertex[0]].x;
374 m_yMaxBoundingBox = m_vertices[m_elements[0].vertex[0]].y;
375 m_zMaxBoundingBox = m_vertices[m_elements[0].vertex[0]].z;
376 m_xMinBoundingBox = m_xMaxBoundingBox;
377 m_yMinBoundingBox = m_yMaxBoundingBox;
378 m_zMinBoundingBox = m_zMaxBoundingBox;
379 m_pMax = m_pMin = m_vertices[m_elements[0].vertex[0]].p;
380 for (
int i = m_nElements; i--;) {
381 for (
int j = 0; j <= m_elements[i].type; ++j) {
382 if (m_vertices[m_elements[i].vertex[j]].x < m_xMinBoundingBox) {
383 m_xMinBoundingBox = m_vertices[m_elements[i].vertex[j]].x;
384 }
else if (m_vertices[m_elements[i].vertex[j]].x > m_xMaxBoundingBox) {
385 m_xMaxBoundingBox = m_vertices[m_elements[i].vertex[j]].x;
387 if (m_vertices[m_elements[i].vertex[j]].y < m_yMinBoundingBox) {
388 m_yMinBoundingBox = m_vertices[m_elements[i].vertex[j]].y;
389 }
else if (m_vertices[m_elements[i].vertex[j]].y > m_yMaxBoundingBox) {
390 m_yMaxBoundingBox = m_vertices[m_elements[i].vertex[j]].y;
392 if (m_vertices[m_elements[i].vertex[j]].z < m_zMinBoundingBox) {
393 m_zMinBoundingBox = m_vertices[m_elements[i].vertex[j]].z;
394 }
else if (m_vertices[m_elements[i].vertex[j]].z > m_zMaxBoundingBox) {
395 m_zMaxBoundingBox = m_vertices[m_elements[i].vertex[j]].z;
397 if (m_vertices[m_elements[i].vertex[j]].p < m_pMin) {
398 m_pMin = m_vertices[m_elements[i].vertex[j]].p;
399 }
else if (m_vertices[m_elements[i].vertex[j]].p > m_pMax) {
400 m_pMax = m_vertices[m_elements[i].vertex[j]].p;
406 std::cout <<
" Bounding box:\n";
407 std::cout <<
" " << m_xMinBoundingBox <<
" < x [cm] < "
408 << m_xMaxBoundingBox <<
"\n";
409 std::cout <<
" " << m_yMinBoundingBox <<
" < y [cm] < "
410 << m_yMaxBoundingBox <<
"\n";
411 std::cout <<
" " << m_zMinBoundingBox <<
" < z [cm] < "
412 << m_zMaxBoundingBox <<
"\n";
413 std::cout <<
" Voltage range:\n";
414 std::cout <<
" " << m_pMin <<
" < V < " << m_pMax <<
"\n";
419 std::vector<int> nElementsRegion;
420 nElementsRegion.resize(m_nRegions);
421 for (
int i = m_nRegions; i--;) nElementsRegion[i] = 0;
426 int nOtherShapes = 0;
430 std::vector<int> looseElements;
431 looseElements.clear();
435 std::vector<int> degenerateElements;
436 degenerateElements.clear();
438 for (
int i = m_nElements; i--;) {
439 if (m_elements[i].type == 2) {
441 if (m_elements[i].vertex[0] == m_elements[i].vertex[1] ||
442 m_elements[i].vertex[1] == m_elements[i].vertex[2] ||
443 m_elements[i].vertex[2] == m_elements[i].vertex[0]) {
444 degenerateElements.push_back(i);
447 }
else if (m_elements[i].type == 5) {
448 if (m_elements[i].vertex[0] == m_elements[i].vertex[1] ||
449 m_elements[i].vertex[0] == m_elements[i].vertex[2] ||
450 m_elements[i].vertex[0] == m_elements[i].vertex[3] ||
451 m_elements[i].vertex[1] == m_elements[i].vertex[2] ||
452 m_elements[i].vertex[1] == m_elements[i].vertex[3] ||
453 m_elements[i].vertex[2] == m_elements[i].vertex[3]) {
454 degenerateElements.push_back(i);
462 if (m_elements[i].region >= 0 && m_elements[i].region < m_nRegions) {
463 ++nElementsRegion[m_elements[i].region];
465 looseElements.push_back(i);
470 if (nDegenerate > 0) {
472 std::cerr <<
" The following elements are degenerate:\n";
473 for (
int i = nDegenerate; i--;) {
474 std::cerr <<
" " << degenerateElements[i] <<
"\n";
481 std::cerr <<
" The following elements are not part of any region:\n";
482 for (
int i = nLoose; i--;) {
483 std::cerr <<
" " << looseElements[i] <<
"\n";
489 std::cout <<
" Number of regions: " << m_nRegions <<
"\n";
490 for (
int i = 0; i < m_nRegions; ++i) {
491 std::cout <<
" " << i <<
": " << m_regions[i].name <<
", "
492 << nElementsRegion[i] <<
" elements\n";
495 std::cout <<
" Number of elements: " << m_nElements <<
"\n";
496 if (nTriangles > 0) {
497 std::cout <<
" " << nTriangles <<
" triangles\n";
499 if (nTetrahedra > 0) {
500 std::cout <<
" " << nTetrahedra <<
" tetrahedra\n";
502 if (nOtherShapes > 0) {
503 std::cout <<
" " << nOtherShapes <<
" elements of unknown type\n";
504 std::cout <<
" Program bug!\n";
511 for (
int i = 0; i < m_nElements; ++i) {
512 if (m_elements[i].type == 2) {
513 std::cout <<
" " << i <<
": " << m_elements[i].vertex[0] <<
" "
514 << m_elements[i].vertex[1] <<
" " << m_elements[i].vertex[2]
515 <<
" (triangle, region " << m_elements[i].region <<
")\n";
516 }
else if (m_elements[i].type == 5) {
517 std::cout <<
" " << i <<
": " << m_elements[i].vertex[0] <<
" "
518 << m_elements[i].vertex[1] <<
" " << m_elements[i].vertex[2]
519 <<
" " << m_elements[i].vertex[3] <<
" (tetrahedron, region "
520 << m_elements[i].region <<
")\n";
525 std::cout <<
" Number of vertices: " << m_nVertices <<
"\n";
527 for (
int i = 0; i < m_nVertices; ++i) {
528 std::cout <<
" " << i <<
": (x, y, z) = (" << m_vertices[i].x <<
", "
529 << m_vertices[i].y <<
", " << m_vertices[i].z
530 <<
"), V = " << m_vertices[i].p <<
"\n";
546 double& xmax,
double& ymax,
double& zmax) {
548 if (!
ready)
return false;
549 xmin = m_xMinBoundingBox;
550 ymin = m_yMinBoundingBox;
551 zmin = m_zMinBoundingBox;
552 xmax = m_xMaxBoundingBox;
553 ymax = m_yMaxBoundingBox;
554 zmax = m_zMaxBoundingBox;
572 if (!
ready)
return false;
583 std::cerr <<
" Field map not yet initialised.\n";
587 if (m_nRegions < 0) {
589 std::cerr <<
" No regions are currently defined.\n";
594 std::cout <<
" Currently " << m_nRegions <<
" regions are defined.\n";
595 std::cout <<
" Index Name Medium\n";
596 for (
int i = 0; i < m_nRegions; ++i) {
597 std::cout <<
" " << i <<
" " << m_regions[i].name;
598 if (m_regions[i].medium == 0) {
599 std::cout <<
" none ";
601 std::cout <<
" " << m_regions[i].medium->GetName();
603 if (m_regions[i].drift) {
604 std::cout <<
" (active region)\n";
613 if (i < 0 || i >= m_nRegions) {
615 std::cerr <<
" Region " << i <<
" does not exist.\n";
618 name = m_regions[i].name;
619 active = m_regions[i].drift;
624 if (i < 0 || i >= m_nRegions) {
626 std::cerr <<
" Region " << i <<
" does not exist.\n";
629 m_regions[i].drift =
true;
634 if (i < 0 || i >= m_nRegions) {
635 std::cerr <<
m_className <<
"::UnsetDriftRegion:\n";
636 std::cerr <<
" Region " << i <<
" does not exist.\n";
639 m_regions[i].drift =
false;
644 if (i < 0 || i >= m_nRegions) {
646 std::cerr <<
" Region " << i <<
" does not exist.\n";
652 std::cerr <<
" Medium pointer is null.\n";
656 m_regions[i].medium = medium;
661 if (i < 0 || i >= m_nRegions) {
663 std::cerr <<
" Region " << i <<
" does not exist.\n";
667 m = m_regions[i].medium;
668 if (m == 0)
return false;
673 double& dmax,
int& type) {
675 if (i < 0 || i >= m_nElements) {
677 std::cerr <<
" Element index (" << i <<
") out of range.\n";
681 type = m_elements[i].type;
682 if (m_elements[i].type == 2) {
684 const double vx = (m_vertices[m_elements[i].vertex[1]].y -
685 m_vertices[m_elements[i].vertex[0]].y) *
686 (m_vertices[m_elements[i].vertex[2]].z -
687 m_vertices[m_elements[i].vertex[0]].z) -
688 (m_vertices[m_elements[i].vertex[1]].z -
689 m_vertices[m_elements[i].vertex[0]].z) *
690 (m_vertices[m_elements[i].vertex[2]].y -
691 m_vertices[m_elements[i].vertex[0]].y);
692 const double vy = (m_vertices[m_elements[i].vertex[1]].z -
693 m_vertices[m_elements[i].vertex[0]].z) *
694 (m_vertices[m_elements[i].vertex[2]].x -
695 m_vertices[m_elements[i].vertex[0]].x) -
696 (m_vertices[m_elements[i].vertex[1]].x -
697 m_vertices[m_elements[i].vertex[0]].x) *
698 (m_vertices[m_elements[i].vertex[2]].z -
699 m_vertices[m_elements[i].vertex[0]].z);
700 const double vz = (m_vertices[m_elements[i].vertex[1]].x -
701 m_vertices[m_elements[i].vertex[0]].x) *
702 (m_vertices[m_elements[i].vertex[2]].y -
703 m_vertices[m_elements[i].vertex[0]].y) -
704 (m_vertices[m_elements[i].vertex[1]].y -
705 m_vertices[m_elements[i].vertex[0]].y) *
706 (m_vertices[m_elements[i].vertex[2]].x -
707 m_vertices[m_elements[i].vertex[0]].x);
708 vol =
sqrt(vx * vx + vy * vy + vz * vz);
709 const double a =
sqrt(
pow(m_vertices[m_elements[i].vertex[1]].x -
710 m_vertices[m_elements[i].vertex[0]].x,
712 pow(m_vertices[m_elements[i].vertex[1]].y -
713 m_vertices[m_elements[i].vertex[0]].y,
715 pow(m_vertices[m_elements[i].vertex[1]].z -
716 m_vertices[m_elements[i].vertex[0]].z,
718 const double b =
sqrt(
pow(m_vertices[m_elements[i].vertex[2]].x -
719 m_vertices[m_elements[i].vertex[0]].x,
721 pow(m_vertices[m_elements[i].vertex[2]].y -
722 m_vertices[m_elements[i].vertex[0]].y,
724 pow(m_vertices[m_elements[i].vertex[2]].z -
725 m_vertices[m_elements[i].vertex[0]].z,
727 const double c =
sqrt(
pow(m_vertices[m_elements[i].vertex[1]].x -
728 m_vertices[m_elements[i].vertex[2]].x,
730 pow(m_vertices[m_elements[i].vertex[1]].y -
731 m_vertices[m_elements[i].vertex[2]].y,
733 pow(m_vertices[m_elements[i].vertex[1]].z -
734 m_vertices[m_elements[i].vertex[2]].z,
737 if (b < dmin) dmin = b;
738 if (c < dmin) dmin = c;
739 if (b > dmax) dmax = b;
740 if (c > dmax) dmax = c;
741 }
else if (m_elements[i].type == 5) {
743 vol =
fabs((m_vertices[m_elements[i].vertex[3]].x -
744 m_vertices[m_elements[i].vertex[0]].x) *
745 ((m_vertices[m_elements[i].vertex[1]].y -
746 m_vertices[m_elements[i].vertex[0]].y) *
747 (m_vertices[m_elements[i].vertex[2]].z -
748 m_vertices[m_elements[i].vertex[0]].z) -
749 (m_vertices[m_elements[i].vertex[2]].y -
750 m_vertices[m_elements[i].vertex[0]].y) *
751 (m_vertices[m_elements[i].vertex[1]].z -
752 m_vertices[m_elements[i].vertex[0]].z)) +
753 (m_vertices[m_elements[i].vertex[3]].y -
754 m_vertices[m_elements[i].vertex[0]].y) *
755 ((m_vertices[m_elements[i].vertex[1]].z -
756 m_vertices[m_elements[i].vertex[0]].z) *
757 (m_vertices[m_elements[i].vertex[2]].x -
758 m_vertices[m_elements[i].vertex[0]].x) -
759 (m_vertices[m_elements[i].vertex[2]].z -
760 m_vertices[m_elements[i].vertex[0]].z) *
761 (m_vertices[m_elements[i].vertex[1]].x -
762 m_vertices[m_elements[i].vertex[0]].x)) +
763 (m_vertices[m_elements[i].vertex[3]].z -
764 m_vertices[m_elements[i].vertex[0]].z) *
765 ((m_vertices[m_elements[i].vertex[1]].x -
766 m_vertices[m_elements[i].vertex[0]].x) *
767 (m_vertices[m_elements[i].vertex[2]].y -
768 m_vertices[m_elements[i].vertex[0]].y) -
769 (m_vertices[m_elements[i].vertex[3]].x -
770 m_vertices[m_elements[i].vertex[0]].x) *
771 (m_vertices[m_elements[i].vertex[1]].y -
772 m_vertices[m_elements[i].vertex[0]].y))) /
775 for (
int j = 0; j < nMaxVertices - 1; ++j) {
776 for (
int k = j + 1; k < nMaxVertices; ++k) {
778 const double dist =
sqrt(
pow(m_vertices[m_elements[i].vertex[j]].x -
779 m_vertices[m_elements[i].vertex[k]].x,
781 pow(m_vertices[m_elements[i].vertex[j]].y -
782 m_vertices[m_elements[i].vertex[k]].y,
784 pow(m_vertices[m_elements[i].vertex[j]].z -
785 m_vertices[m_elements[i].vertex[k]].z,
791 if (dist < dmin) dmin = dist;
792 if (dist > dmax) dmax = dist;
798 std::cerr <<
" Unexpected element type (" << type <<
").\n";
805 double& dmax,
int& type,
int& node1,
806 int& node2,
int& node3,
int& node4,
int& node5,
807 int& node6,
int& node7,
int& reg) {
809 if (!
GetElement(i, vol, dmin, dmax, type))
return false;
810 node1 = m_elements[i].vertex[0];
811 node2 = m_elements[i].vertex[1];
812 node3 = m_elements[i].vertex[2];
813 node4 = m_elements[i].vertex[3];
814 node5 = m_elements[i].vertex[4];
815 node6 = m_elements[i].vertex[5];
816 node7 = m_elements[i].vertex[6];
817 reg = m_elements[i].region;
822 double& v,
double& ex,
double& ey,
double& ez) {
824 if (i < 0 || i >= m_nVertices) {
826 std::cerr <<
" Node index (" << i <<
") out of range.\n";
834 ex = m_vertices[i].ex;
835 ey = m_vertices[i].ey;
836 ez = m_vertices[i].ez;
840bool ComponentTcad3d::LoadData(
const std::string datafilename) {
842 std::ifstream datafile;
843 datafile.open(datafilename.c_str(), std::ios::in);
846 std::cerr <<
" Could not open file " << datafilename <<
".\n";
851 std::istringstream data;
853 std::vector<bool> isInRegion(m_nVertices);
854 std::vector<int> fillCount(m_nVertices, 0);
855 for (
int i = m_nVertices; i--;) {
856 m_vertices[i].p = 0.;
857 m_vertices[i].ex = 0.;
858 m_vertices[i].ey = 0.;
859 m_vertices[i].ez = 0.;
860 m_vertices[i].isShared =
false;
863 std::string::size_type pBra, pKet, pEq;
865 while (!datafile.fail()) {
867 std::getline(datafile, line);
869 line.erase(line.begin(),
870 std::find_if(line.begin(), line.end(),
871 not1(std::ptr_fun<int, int>(isspace))));
873 if (line.substr(0, 8) ==
"function") {
875 pEq = line.find(
'=');
876 if (pEq == std::string::npos) {
879 std::cerr <<
" Error reading file " << datafilename <<
".\n";
880 std::cerr <<
" Line:\n";
881 std::cerr <<
" " << line <<
"\n";
886 line = line.substr(pEq + 1);
891 if (dataset ==
"ElectrostaticPotential") {
892 std::getline(datafile, line);
893 std::getline(datafile, line);
894 std::getline(datafile, line);
895 std::getline(datafile, line);
897 pBra = line.find(
'[');
898 pKet = line.find(
']');
899 if (pKet < pBra || pBra == std::string::npos ||
900 pKet == std::string::npos) {
902 std::cerr <<
" Error reading file " << datafilename <<
"\n";
903 std::cerr <<
" Line:\n";
904 std::cerr <<
" " << line <<
"\n";
909 line = line.substr(pBra + 1, pKet - pBra - 1);
916 for (
int j = 0; j < m_nRegions; ++j) {
917 if (name == m_regions[j].name) {
924 std::cerr <<
" Error reading file " << datafilename <<
"\n";
925 std::cerr <<
" Unknown region " << name <<
".\n";
929 std::getline(datafile, line);
930 pBra = line.find(
'(');
931 pKet = line.find(
')');
932 if (pKet < pBra || pBra == std::string::npos ||
933 pKet == std::string::npos) {
935 std::cerr <<
" Error reading file " << datafilename <<
"\n";
936 std::cerr <<
" Line:\n";
937 std::cerr <<
" " << line <<
"\n";
942 line = line.substr(pBra + 1, pKet - pBra - 1);
948 for (
int j = m_nVertices; j--;) isInRegion[j] =
false;
949 for (
int j = 0; j < m_nElements; ++j) {
950 if (m_elements[j].region != index)
continue;
951 for (
int k = 0; k <= m_elements[j].type; ++k) {
952 isInRegion[m_elements[j].vertex[k]] =
true;
957 for (
int j = 0; j < nValues; ++j) {
961 while (ivertex < m_nVertices) {
962 if (isInRegion[ivertex])
break;
967 if (ivertex >= m_nVertices) {
969 std::cerr <<
" Error reading file " << datafilename <<
"\n";
970 std::cerr <<
" Dataset has more values than "
971 <<
"there are vertices in region " << name <<
"\n";
976 m_vertices[ivertex].p = val;
977 ++fillCount[ivertex];
980 }
else if (dataset ==
"ElectricField") {
982 std::getline(datafile, line);
983 std::getline(datafile, line);
984 std::getline(datafile, line);
985 std::getline(datafile, line);
986 pBra = line.find(
'[');
987 pKet = line.find(
']');
988 if (pKet < pBra || pBra == std::string::npos ||
989 pKet == std::string::npos) {
991 std::cerr <<
" Error reading file " << datafilename <<
".\n";
992 std::cerr <<
" Line:\n";
993 std::cerr <<
" " << line <<
"\n";
998 line = line.substr(pBra + 1, pKet - pBra - 1);
1004 for (
int j = 0; j < m_nRegions; ++j) {
1005 if (name == m_regions[j].name) {
1012 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1013 std::cerr <<
" Unknown region " << name <<
".\n";
1016 std::getline(datafile, line);
1017 pBra = line.find(
'(');
1018 pKet = line.find(
')');
1019 if (pKet < pBra || pBra == std::string::npos ||
1020 pKet == std::string::npos) {
1022 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1023 std::cerr <<
" Line:\n";
1024 std::cerr <<
" " << line <<
"\n";
1029 line = line.substr(pBra + 1, pKet - pBra - 1);
1035 nValues = nValues / 3;
1036 for (
int j = m_nVertices; j--;) isInRegion[j] =
false;
1037 for (
int j = 0; j < m_nElements; ++j) {
1038 if (m_elements[j].region != index)
continue;
1039 for (
int k = 0; k <= m_elements[j].type; ++k) {
1040 isInRegion[m_elements[j].vertex[k]] =
true;
1044 double val1, val2, val3;
1045 for (
int j = 0; j < nValues; ++j) {
1046 datafile >> val1 >> val2 >> val3;
1047 while (ivertex < m_nVertices) {
1048 if (isInRegion[ivertex])
break;
1051 if (ivertex >= m_nVertices) {
1053 <<
" Error reading file " << datafilename <<
"\n"
1054 <<
" Dataset has more values than"
1055 <<
" there are vertices in region " << name <<
".\n";
1060 m_vertices[ivertex].ex = val1;
1061 m_vertices[ivertex].ey = val2;
1062 m_vertices[ivertex].ez = val3;
1068 if (datafile.fail() && !datafile.eof()) {
1070 std::cerr <<
" Error reading file " << datafilename <<
"\n";
1076 for (
int i = m_nVertices; i--;) {
1077 if (fillCount[i] > 1) m_vertices[i].isShared =
true;
1085bool ComponentTcad3d::LoadGrid(
const std::string gridfilename) {
1088 std::ifstream gridfile;
1089 gridfile.open(gridfilename.c_str(), std::ios::in);
1092 std::cerr <<
" Could not open file " << gridfilename <<
".\n";
1097 std::istringstream data;
1101 std::string::size_type pBra, pKet, pEq;
1106 while (!gridfile.fail()) {
1108 std::getline(gridfile, line);
1111 line.erase(line.begin(), find_if(line.begin(), line.end(),
1112 not1(std::ptr_fun<int, int>(isspace))));
1114 if (line.substr(0, 10) ==
"nb_regions") {
1115 pEq = line.find(
'=');
1116 if (pEq == std::string::npos) {
1119 std::cerr <<
" Could not read number of regions.\n";
1124 line = line.substr(pEq + 1);
1130 if (gridfile.fail())
break;
1132 if (gridfile.eof()) {
1135 std::cerr <<
" Could not find entry 'nb_regions' in file\n";
1136 std::cerr <<
" " << gridfilename <<
".\n";
1140 }
else if (gridfile.fail()) {
1143 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1149 m_regions.resize(m_nRegions);
1150 for (
int j = m_nRegions; j--;) {
1151 m_regions[j].name =
"";
1152 m_regions[j].drift =
false;
1153 m_regions[j].medium = 0;
1158 std::cout <<
" Found " << m_nRegions <<
" regions.\n";
1162 while (!gridfile.fail()) {
1163 std::getline(gridfile, line);
1165 line.erase(line.begin(), find_if(line.begin(), line.end(),
1166 not1(std::ptr_fun<int, int>(isspace))));
1168 if (line.substr(0, 7) ==
"regions") {
1170 pBra = line.find(
'[');
1171 pKet = line.find(
']');
1172 if (pKet < pBra || pBra == std::string::npos ||
1173 pKet == std::string::npos) {
1176 std::cerr <<
" Could not read region names.\n";
1181 line = line.substr(pBra + 1, pKet - pBra - 1);
1183 for (
int j = 0; j < m_nRegions; ++j) {
1184 data >> m_regions[j].name;
1187 m_regions[j].drift =
true;
1188 m_regions[j].medium = 0;
1193 if (gridfile.eof()) {
1196 std::cerr <<
" Could not find entry 'regions' in file\n";
1197 std::cerr <<
" " << gridfilename <<
".\n";
1201 }
else if (gridfile.fail()) {
1204 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1212 while (!gridfile.fail()) {
1213 std::getline(gridfile, line);
1215 line.erase(line.begin(), find_if(line.begin(), line.end(),
1216 not1(std::ptr_fun<int, int>(isspace))));
1218 if (line.substr(0, 8) ==
"Vertices") {
1220 pBra = line.find(
'(');
1221 pKet = line.find(
')');
1222 if (pKet < pBra || pBra == std::string::npos ||
1223 pKet == std::string::npos) {
1226 std::cerr <<
" Could not read number of vertices.\n";
1231 line = line.substr(pBra + 1, pKet - pBra - 1);
1233 data >> m_nVertices;
1235 m_vertices.resize(m_nVertices);
1237 for (
int j = 0; j < m_nVertices; ++j) {
1238 gridfile >> m_vertices[j].x >> m_vertices[j].y >> m_vertices[j].z;
1240 m_vertices[j].x *= 1.e-4;
1241 m_vertices[j].y *= 1.e-4;
1242 m_vertices[j].z *= 1.e-4;
1244 iLine += m_nVertices - 1;
1248 if (gridfile.eof()) {
1250 std::cerr <<
" Could not find section 'Vertices' in file\n";
1251 std::cerr <<
" " << gridfilename <<
".\n";
1255 }
else if (gridfile.fail()) {
1257 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1267 std::vector<int> edgeP1;
1268 std::vector<int> edgeP2;
1269 while (!gridfile.fail()) {
1270 std::getline(gridfile, line);
1272 line.erase(line.begin(), find_if(line.begin(), line.end(),
1273 not1(std::ptr_fun<int, int>(isspace))));
1275 if (line.substr(0, 5) ==
"Edges") {
1277 pBra = line.find(
'(');
1278 pKet = line.find(
')');
1279 if (pKet < pBra || pBra == std::string::npos ||
1280 pKet == std::string::npos) {
1283 std::cerr <<
" Could not read number of edges.\n";
1288 line = line.substr(pBra + 1, pKet - pBra - 1);
1292 edgeP1.resize(nEdges);
1293 edgeP2.resize(nEdges);
1295 for (
int j = 0; j < nEdges; ++j) {
1296 gridfile >> edgeP1[j] >> edgeP2[j];
1298 iLine += nEdges - 1;
1302 if (gridfile.eof()) {
1304 std::cerr <<
" Could not find section 'Edges' in file\n";
1305 std::cerr <<
" " << gridfilename <<
".\n";
1309 }
else if (gridfile.fail()) {
1311 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1318 for (
int i = nEdges; i--;) {
1320 if (edgeP1[i] < 0 || edgeP1[i] >= m_nVertices || edgeP2[i] < 0 ||
1321 edgeP2[i] >= m_nVertices) {
1323 std::cerr <<
" Vertex index of edge " << i <<
" out of range.\n";
1329 if (edgeP1[i] == edgeP2[i]) {
1331 std::cerr <<
" Edge " << i <<
" is degenerate.\n";
1340 std::vector<face> faces;
1343 while (!gridfile.fail()) {
1344 std::getline(gridfile, line);
1346 line.erase(line.begin(), find_if(line.begin(), line.end(),
1347 not1(std::ptr_fun<int, int>(isspace))));
1349 if (line.substr(0, 5) ==
"Faces") {
1351 pBra = line.find(
'(');
1352 pKet = line.find(
')');
1353 if (pKet < pBra || pBra == std::string::npos ||
1354 pKet == std::string::npos) {
1357 std::cerr <<
" Could not read number of faces.\n";
1362 line = line.substr(pBra + 1, pKet - pBra - 1);
1366 faces.resize(nFaces);
1368 for (
int j = 0; j < nFaces; ++j) {
1369 gridfile >> faces[j].type;
1370 if (faces[j].type != 3 && faces[j].type != 4) {
1372 std::cerr <<
" Face with index " << j
1373 <<
" has invalid number of edges (" << faces[j].type
1379 for (
int k = 0; k < faces[j].type; ++k) {
1380 gridfile >> faces[j].edge[k];
1383 iLine += nFaces - 1;
1387 if (gridfile.eof()) {
1389 std::cerr <<
" Could not find section 'Faces' in file\n";
1390 std::cerr <<
" " << gridfilename <<
".\n";
1394 }
else if (gridfile.fail()) {
1396 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1404 int edge0, edge1, edge2;
1405 int face0, face1, face2, face3;
1407 while (!gridfile.fail()) {
1408 std::getline(gridfile, line);
1410 line.erase(line.begin(), find_if(line.begin(), line.end(),
1411 not1(std::ptr_fun<int, int>(isspace))));
1413 if (line.substr(0, 8) ==
"Elements") {
1415 pBra = line.find(
'(');
1416 pKet = line.find(
')');
1417 if (pKet < pBra || pBra == std::string::npos ||
1418 pKet == std::string::npos) {
1421 std::cerr <<
" Could not read number of elements.\n";
1426 line = line.substr(pBra + 1, pKet - pBra - 1);
1428 data >> m_nElements;
1431 m_elements.resize(m_nElements);
1433 for (
int j = 0; j < m_nElements; ++j) {
1438 gridfile >> edge0 >> edge1 >> edge2;
1445 if (edge0 >= nEdges || -edge0 - 1 >= nEdges || edge1 >= nEdges ||
1446 -edge1 - 1 >= nEdges || edge2 >= nEdges || -edge2 - 1 >= nEdges) {
1448 std::cerr <<
" Error reading file " << gridfilename <<
" (line "
1450 std::cerr <<
" Edge index out of range.\n";
1455 if (edge0 < 0) edge0 = -edge0 - 1;
1456 if (edge1 < 0) edge1 = -edge1 - 1;
1457 m_elements[j].vertex[0] = edgeP1[edge0];
1458 m_elements[j].vertex[1] = edgeP2[edge0];
1459 if (edgeP1[edge1] != m_elements[j].vertex[0] &&
1460 edgeP1[edge1] != m_elements[j].vertex[1]) {
1461 m_elements[j].vertex[2] = edgeP1[edge1];
1463 m_elements[j].vertex[2] = edgeP2[edge1];
1465 }
else if (type == 5) {
1471 gridfile >> face0 >> face1 >> face2 >> face3;
1473 if (face0 >= nFaces || -face0 - 1 >= nFaces || face1 >= nFaces ||
1474 -face1 - 1 >= nFaces || face2 >= nFaces || -face2 - 1 >= nFaces ||
1475 face3 >= nFaces || -face3 - 1 >= nFaces) {
1477 std::cerr <<
" Error reading file " << gridfilename <<
" (line "
1479 std::cerr <<
" Face index out of range.\n";
1484 if (face0 < 0) face0 = -face0 - 1;
1485 if (face1 < 0) face1 = -face1 - 1;
1487 edge0 = faces[face0].edge[0];
1488 edge1 = faces[face0].edge[1];
1489 edge2 = faces[face0].edge[2];
1490 if (edge0 < 0) edge0 = -edge0 - 1;
1491 if (edge1 < 0) edge1 = -edge1 - 1;
1492 if (edge2 < 0) edge2 = -edge2 - 1;
1494 if (edge0 >= nEdges || edge1 >= nEdges || edge2 >= nEdges) {
1496 std::cerr <<
" Error reading file " << gridfilename <<
"\n";
1497 std::cerr <<
" Edge index in element " << j
1498 <<
" out of range.\n";
1504 m_elements[j].vertex[0] = edgeP1[edge0];
1505 m_elements[j].vertex[1] = edgeP2[edge0];
1506 if (edgeP1[edge1] != m_elements[j].vertex[0] &&
1507 edgeP1[edge1] != m_elements[j].vertex[1]) {
1508 m_elements[j].vertex[2] = edgeP1[edge1];
1510 m_elements[j].vertex[2] = edgeP2[edge1];
1513 edge0 = faces[face1].edge[0];
1514 edge1 = faces[face1].edge[1];
1515 edge2 = faces[face1].edge[2];
1516 if (edge0 < 0) edge0 = -edge0 - 1;
1517 if (edge1 < 0) edge1 = -edge1 - 1;
1518 if (edge2 < 0) edge2 = -edge2 - 1;
1519 if (edgeP1[edge0] != m_elements[j].vertex[0] &&
1520 edgeP1[edge0] != m_elements[j].vertex[1] &&
1521 edgeP1[edge0] != m_elements[j].vertex[2]) {
1522 m_elements[j].vertex[3] = edgeP1[edge0];
1523 }
else if (edgeP2[edge0] != m_elements[j].vertex[0] &&
1524 edgeP2[edge0] != m_elements[j].vertex[1] &&
1525 edgeP2[edge0] != m_elements[j].vertex[2]) {
1526 m_elements[j].vertex[3] = edgeP2[edge0];
1527 }
else if (edgeP1[edge1] != m_elements[j].vertex[0] &&
1528 edgeP1[edge1] != m_elements[j].vertex[1] &&
1529 edgeP1[edge1] != m_elements[j].vertex[2]) {
1530 m_elements[j].vertex[3] = edgeP1[edge1];
1531 }
else if (edgeP2[edge1] != m_elements[j].vertex[0] &&
1532 edgeP2[edge1] != m_elements[j].vertex[1] &&
1533 edgeP2[edge1] != m_elements[j].vertex[2]) {
1534 m_elements[j].vertex[3] = edgeP2[edge1];
1537 std::cerr <<
" Error reading file " << gridfilename <<
"\n";
1538 std::cerr <<
" Face 1 of element " << j <<
" is degenerate.\n";
1546 <<
" Error reading file " << gridfilename <<
" (line "
1548 if (type == 0 || type == 1) {
1549 std::cerr <<
" Invalid element type (" << type
1550 <<
") for 3d mesh.\n";
1552 std::cerr <<
" Element type " << type <<
" is not supported.\n";
1553 std::cerr <<
" Remesh with option -t to create only"
1554 <<
" triangles and tetrahedra.\n";
1560 m_elements[j].type = type;
1561 m_elements[j].region = -1;
1566 if (gridfile.eof()) {
1568 std::cerr <<
" Could not find section 'Elements' in file\n";
1569 std::cerr <<
" " << gridfilename <<
".\n";
1573 }
else if (gridfile.fail()) {
1575 std::cerr <<
" Error reading file " << gridfilename <<
" (line " << iLine
1584 while (!gridfile.fail()) {
1585 std::getline(gridfile, line);
1586 line.erase(line.begin(), find_if(line.begin(), line.end(),
1587 not1(std::ptr_fun<int, int>(isspace))));
1589 if (line.substr(0, 6) ==
"Region") {
1591 pBra = line.find(
'(');
1592 pKet = line.find(
')');
1593 if (pKet < pBra || pBra == std::string::npos ||
1594 pKet == std::string::npos) {
1596 std::cerr <<
" Could not read region name.\n";
1601 line = line.substr(pBra + 1, pKet - pBra - 1);
1606 for (
int j = 0; j < m_nRegions; ++j) {
1607 if (name == m_regions[j].name) {
1615 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
1616 std::cerr <<
" Unknown region " << name <<
".\n";
1619 std::getline(gridfile, line);
1620 std::getline(gridfile, line);
1621 pBra = line.find(
'(');
1622 pKet = line.find(
')');
1623 if (pKet < pBra || pBra == std::string::npos ||
1624 pKet == std::string::npos) {
1627 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
1628 std::cerr <<
" Could not read number of elements in region " << name
1634 line = line.substr(pBra + 1, pKet - pBra - 1);
1635 int nElementsRegion;
1638 data >> nElementsRegion;
1640 for (
int j = 0; j < nElementsRegion; ++j) {
1641 gridfile >> iElement;
1642 m_elements[iElement].region = index;
1648 if (gridfile.fail() && !gridfile.eof()) {
1650 std::cerr <<
" Error reading file " << gridfilename <<
".\n";
1658void ComponentTcad3d::Cleanup() {
1673bool ComponentTcad3d::CheckTetrahedron(
const double x,
const double y,
1674 const double z,
const int i) {
1676 m_w[0] = m_w[1] = m_w[2] = m_w[3] = 0.;
1678 const double x10 = m_vertices[m_elements[i].vertex[1]].x -
1679 m_vertices[m_elements[i].vertex[0]].x;
1680 const double y10 = m_vertices[m_elements[i].vertex[1]].y -
1681 m_vertices[m_elements[i].vertex[0]].y;
1682 const double z10 = m_vertices[m_elements[i].vertex[1]].z -
1683 m_vertices[m_elements[i].vertex[0]].z;
1685 const double x20 = m_vertices[m_elements[i].vertex[2]].x -
1686 m_vertices[m_elements[i].vertex[0]].x;
1687 const double y20 = m_vertices[m_elements[i].vertex[2]].y -
1688 m_vertices[m_elements[i].vertex[0]].y;
1689 const double z20 = m_vertices[m_elements[i].vertex[2]].z -
1690 m_vertices[m_elements[i].vertex[0]].z;
1692 const double x30 = m_vertices[m_elements[i].vertex[3]].x -
1693 m_vertices[m_elements[i].vertex[0]].x;
1694 const double y30 = m_vertices[m_elements[i].vertex[3]].y -
1695 m_vertices[m_elements[i].vertex[0]].y;
1696 const double z30 = m_vertices[m_elements[i].vertex[3]].z -
1697 m_vertices[m_elements[i].vertex[0]].z;
1699 const double x21 = m_vertices[m_elements[i].vertex[2]].x -
1700 m_vertices[m_elements[i].vertex[1]].x;
1701 const double y21 = m_vertices[m_elements[i].vertex[2]].y -
1702 m_vertices[m_elements[i].vertex[1]].y;
1703 const double z21 = m_vertices[m_elements[i].vertex[2]].z -
1704 m_vertices[m_elements[i].vertex[1]].z;
1706 const double x31 = m_vertices[m_elements[i].vertex[3]].x -
1707 m_vertices[m_elements[i].vertex[1]].x;
1708 const double y31 = m_vertices[m_elements[i].vertex[3]].y -
1709 m_vertices[m_elements[i].vertex[1]].y;
1710 const double z31 = m_vertices[m_elements[i].vertex[3]].z -
1711 m_vertices[m_elements[i].vertex[1]].z;
1713 const double x32 = m_vertices[m_elements[i].vertex[3]].x -
1714 m_vertices[m_elements[i].vertex[2]].x;
1715 const double y32 = m_vertices[m_elements[i].vertex[3]].y -
1716 m_vertices[m_elements[i].vertex[2]].y;
1717 const double z32 = m_vertices[m_elements[i].vertex[3]].z -
1718 m_vertices[m_elements[i].vertex[2]].z;
1721 (x - m_vertices[m_elements[i].vertex[1]].x) * (y21 * z31 - y31 * z21) +
1722 (y - m_vertices[m_elements[i].vertex[1]].y) * (z21 * x31 - z31 * x21) +
1723 (z - m_vertices[m_elements[i].vertex[1]].z) * (x21 * y31 - x31 * y21);
1725 m_w[0] /= x10 * (y31 * z21 - y21 * z31) + y10 * (z31 * x21 - z21 * x31) +
1726 z10 * (x31 * y21 - x21 * y31);
1728 if (m_w[0] < 0.)
return false;
1731 (x - m_vertices[m_elements[i].vertex[2]].x) * (-y20 * z32 + y32 * z20) +
1732 (y - m_vertices[m_elements[i].vertex[2]].y) * (-z20 * x32 + z32 * x20) +
1733 (z - m_vertices[m_elements[i].vertex[2]].z) * (-x20 * y32 + x32 * y20);
1735 m_w[1] /= x21 * (y20 * z32 - y32 * z20) + y21 * (z20 * x32 - z32 * x20) +
1736 z21 * (x20 * y32 - x32 * y20);
1738 if (m_w[1] < 0.)
return false;
1741 (x - m_vertices[m_elements[i].vertex[3]].x) * (y30 * z31 - y31 * z30) +
1742 (y - m_vertices[m_elements[i].vertex[3]].y) * (z30 * x31 - z31 * x30) +
1743 (z - m_vertices[m_elements[i].vertex[3]].z) * (x30 * y31 - x31 * y30);
1745 m_w[2] /= x32 * (y31 * z30 - y30 * z31) + y32 * (z31 * x30 - z30 * x31) +
1746 z32 * (x31 * y30 - x30 * y31);
1748 if (m_w[2] < 0.)
return false;
1751 (x - m_vertices[m_elements[i].vertex[0]].x) * (y20 * z10 - y10 * z20) +
1752 (y - m_vertices[m_elements[i].vertex[0]].y) * (z20 * x10 - z10 * x20) +
1753 (z - m_vertices[m_elements[i].vertex[0]].z) * (x20 * y10 - x10 * y20);
1755 m_w[3] /= x30 * (y20 * z10 - y10 * z20) + y30 * (z20 * x10 - z10 * x20) +
1756 z30 * (x20 * y10 - x10 * y20);
1758 if (m_w[3] < 0.)
return false;
1762 const double xr = m_w[0] * m_vertices[m_elements[i].vertex[0]].x +
1763 m_w[1] * m_vertices[m_elements[i].vertex[1]].x +
1764 m_w[2] * m_vertices[m_elements[i].vertex[2]].x +
1765 m_w[3] * m_vertices[m_elements[i].vertex[3]].x;
1766 const double yr = m_w[0] * m_vertices[m_elements[i].vertex[0]].y +
1767 m_w[1] * m_vertices[m_elements[i].vertex[1]].y +
1768 m_w[2] * m_vertices[m_elements[i].vertex[2]].y +
1769 m_w[3] * m_vertices[m_elements[i].vertex[3]].y;
1770 const double zr = m_w[0] * m_vertices[m_elements[i].vertex[0]].z +
1771 m_w[1] * m_vertices[m_elements[i].vertex[1]].z +
1772 m_w[2] * m_vertices[m_elements[i].vertex[2]].z +
1773 m_w[3] * m_vertices[m_elements[i].vertex[3]].z;
1774 std::cout <<
m_className <<
"::CheckTetrahedron:\n";
1775 std::cout <<
" Original coordinates: (" << x <<
", " << y <<
", "
1777 std::cout <<
" Local coordinates: (" << m_w[0] <<
", " << m_w[1]
1778 <<
", " << m_w[2] <<
", " << m_w[3] <<
")\n";
1779 std::cerr <<
" Reconstructed coordinates: (" << xr <<
", " << yr <<
", "
1781 std::cerr <<
" Checksum: " << m_w[0] + m_w[1] + m_w[2] + m_w[3] - 1.
1788bool ComponentTcad3d::CheckTriangle(
const double x,
const double y,
1789 const double z,
const int i) {
1791 const double v1x = m_vertices[m_elements[i].vertex[1]].x -
1792 m_vertices[m_elements[i].vertex[0]].x;
1793 const double v2x = m_vertices[m_elements[i].vertex[2]].x -
1794 m_vertices[m_elements[i].vertex[0]].x;
1795 const double v1y = m_vertices[m_elements[i].vertex[1]].y -
1796 m_vertices[m_elements[i].vertex[0]].y;
1797 const double v2y = m_vertices[m_elements[i].vertex[2]].y -
1798 m_vertices[m_elements[i].vertex[0]].y;
1799 const double v1z = m_vertices[m_elements[i].vertex[1]].z -
1800 m_vertices[m_elements[i].vertex[0]].z;
1801 const double v2z = m_vertices[m_elements[i].vertex[2]].z -
1802 m_vertices[m_elements[i].vertex[0]].z;
1806 const double a = v1y * v2z - v2y * v1z;
1807 const double b = v1z * v2x - v2z * v1x;
1808 const double c = v1x * v2y - v2x * v1y;
1809 const double d = a * m_vertices[m_elements[i].vertex[0]].x +
1810 b * m_vertices[m_elements[i].vertex[0]].y +
1811 c * m_vertices[m_elements[i].vertex[0]].z;
1813 if (a * x + b * y + c * z != d)
return false;
1820 m_w[1] = ((x - m_vertices[m_elements[i].vertex[0]].x) * v2y -
1821 (y - m_vertices[m_elements[i].vertex[0]].y) * v2x) /
1822 (v1x * v2y - v1y * v2x);
1823 if (m_w[1] < 0. || m_w[1] > 1.)
return false;
1825 m_w[2] = ((m_vertices[m_elements[i].vertex[0]].x - x) * v1y -
1826 (m_vertices[m_elements[i].vertex[0]].y - y) * v1x) /
1827 (v1x * v2y - v1y * v2x);
1828 if (m_w[2] < 0. || m_w[1] + m_w[2] > 1.)
return false;
1831 m_w[0] = 1. - m_w[1] - m_w[2];
1836void ComponentTcad3d::Reset() {
1842void ComponentTcad3d::UpdatePeriodicity() {
1845 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1846 std::cerr <<
" Field map not available.\n";
1852 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1853 std::cerr <<
" Both simple and mirror periodicity\n";
1854 std::cerr <<
" along x requested; reset.\n";
1859 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1860 std::cerr <<
" Both simple and mirror periodicity\n";
1861 std::cerr <<
" along y requested; reset.\n";
1866 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1867 std::cerr <<
" Both simple and mirror periodicity\n";
1868 std::cerr <<
" along z requested; reset.\n";
1873 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1874 std::cerr <<
" Axial symmetry is not supported; reset.\n";
1879 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
1880 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 GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
bool Initialise(const std::string gridfilename, const std::string datafilename)
void UnsetDriftRegion(const int ireg)
void SetMedium(const int ireg, Medium *m)
void GetRegion(const int ireg, std::string &name, bool &active)
Medium * GetMedium(const double &x, const double &y, const double &z)
bool GetElement(const int i, double &vol, double &dmin, double &dmax, int &type)
bool GetVoltageRange(double &vmin, double &vmax)
bool GetNode(const int i, double &x, double &y, double &z, double &v, double &ex, double &ey, double &ez)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
void SetDriftRegion(const int ireg)