26 <<
" No materials are currently defined.\n";
32 <<
" Currently " << nMaterials <<
" materials are defined.\n"
33 <<
" Index Permittivity Resistivity Notes\n";
34 for (
size_t i = 0; i < nMaterials; ++i) {
37 std::string name =
m_materials[i].medium->GetName();
38 std::cout <<
" " << name;
39 if (
m_materials[i].medium->IsDriftable()) std::cout <<
", drift medium";
40 if (
m_materials[i].medium->IsIonisable()) std::cout <<
", ionisable";
43 std::cout <<
" (drift medium)\n";
56 std::cerr <<
m_className <<
"::DriftMedium: Index out of range.\n";
70 std::cerr <<
m_className <<
"::NotDriftMedium: Index out of range.\n";
80 std::cerr <<
m_className <<
"::GetPermittivity: Index out of range.\n";
89 std::cerr <<
m_className <<
"::GetConductivity: Index out of range.\n";
98 std::cerr <<
m_className <<
"::SetMedium: Index out of range.\n";
103 std::cerr <<
m_className <<
"::SetMedium: Null pointer.\n";
108 std::cout <<
m_className <<
"::SetMedium:\n Associated material " << imat
109 <<
" with medium " << m->
GetName() <<
".\n";
117 std::cerr <<
m_className <<
"::GetMedium: Index out of range.\n";
125 double& dmin,
double& dmax) {
127 std::cerr <<
m_className <<
"::GetElement: Index out of range.\n";
137 std::vector<size_t>& nodes)
const {
139 std::cerr <<
m_className <<
"::GetElement: Index out of range.\n";
143 mat = element.matmap;
146 for (
size_t j = 0; j < 4; ++j) nodes[j] = element.emap[j];
153 std::cerr <<
m_className <<
"::GetNode: Index out of range.\n";
168 for (
size_t i = 0; i < nMaterials; ++i) {
173 std::cerr <<
m_className <<
"::SetDefaultDriftMedium:\n"
174 <<
" Material " << i <<
" has zero permittivity.\n";
176 }
else if (epsmin < 0. || epsmin >
m_materials[i].eps) {
182 std::cerr <<
m_className <<
"::SetDefaultDriftMedium:\n"
183 <<
" Found no material with positive permittivity.\n";
191 double const z,
double& t1,
double& t2,
192 double& t3,
double& t4,
double jac[4][4],
195 if (!m_cacheElemBoundingBoxes) {
196 m_cacheElemBoundingBoxes =
true;
200 std::vector<int> tetList;
201 if (m_useTetrahedralTree && m_octree) {
202 tetList = m_octree->GetElementsInBlock(
Vec3(x, y, z));
205 double jacbak[4][4], detbak = 1.;
206 double t1bak = 0., t2bak = 0., t3bak = 0., t4bak = 0.;
210 t1 = t2 = t3 = t4 = 0;
213 if (m_lastElement > -1 && !m_checkMultipleElement) {
216 if (Coordinates3(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
217 if (t1 >= 0 && t1 <= +1 && t2 >= 0 && t2 <= +1 && t3 >= 0 && t3 <= +1) {
218 return m_lastElement;
222 if (Coordinates5(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
223 if (t1 >= -1 && t1 <= +1 && t2 >= -1 && t2 <= +1)
return m_lastElement;
234 const int numElemToSearch =
235 m_useTetrahedralTree ? tetList.size() :
m_elements.size();
236 for (
int i = 0; i < numElemToSearch; ++i) {
237 const int idxToElemList = m_useTetrahedralTree ? tetList[i] : i;
239 if (x < element.
bbMin[0] || x > element.
bbMax[0] ||
240 y < element.
bbMin[1] || y > element.
bbMax[1] ||
245 if (Coordinates3(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
248 if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1 || t3 < 0 || t3 > 1)
continue;
250 imap = idxToElemList;
251 m_lastElement = idxToElemList;
254 std::cout <<
" Found matching degenerate element " << idxToElemList
257 if (!m_checkMultipleElement)
return idxToElemList;
258 for (
int j = 0; j < 4; ++j) {
259 for (
int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
268 PrintElement(
"FindElement5", x, y, z, t1, t2, t3, t4, element, 6);
272 if (Coordinates5(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
275 if (t1 < -1 || t1 > 1 || t2 < -1 || t2 > 1)
continue;
277 imap = idxToElemList;
278 m_lastElement = idxToElemList;
281 std::cout <<
" Found matching non-degenerate element "
282 << idxToElemList <<
".\n";
284 if (!m_checkMultipleElement)
return idxToElemList;
285 for (
int j = 0; j < 4; ++j) {
286 for (
int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
295 PrintElement(
"FindElement5", x, y, z, t1, t2, t3, t4, element, 8);
301 if (m_checkMultipleElement) {
305 std::cout <<
" No element matching point (" << x <<
", " << y
313 std::cout <<
" Found " << nfound <<
" elements matching point (" << x
314 <<
", " << y <<
").\n";
316 for (
int j = 0; j < 4; ++j) {
317 for (
int k = 0; k < 4; ++k) jac[j][k] = jacbak[j][k];
325 m_lastElement = imap;
331 std::cout <<
" No element matching point (" << x <<
", " << y
338 const double z,
double& t1,
double& t2,
339 double& t3,
double& t4,
double jac[4][4],
344 double t1bak = 0., t2bak = 0., t3bak = 0., t4bak = 0.;
348 t1 = t2 = t3 = t4 = 0.;
351 if (m_lastElement > -1 && !m_checkMultipleElement) {
353 if (Coordinates13(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
354 if (t1 >= 0 && t1 <= +1 && t2 >= 0 && t2 <= +1 && t3 >= 0 && t3 <= +1 &&
355 t4 >= 0 && t4 <= +1) {
356 return m_lastElement;
362 std::vector<int> tetList;
363 if (m_useTetrahedralTree && m_octree) {
364 tetList = m_octree->GetElementsInBlock(
Vec3(x, y, z));
368 const int numElemToSearch =
369 m_useTetrahedralTree ? tetList.size() :
m_elements.size();
375 for (
int i = 0; i < numElemToSearch; i++) {
376 const int idxToElemList = m_useTetrahedralTree ? tetList[i] : i;
378 if (x < element.
bbMin[0] || x > element.
bbMax[0] ||
379 y < element.
bbMin[1] || y > element.
bbMax[1] ||
382 if (Coordinates13(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
385 if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1 || t3 < 0 || t3 > 1 || t4 < 0 ||
390 imap = idxToElemList;
391 m_lastElement = idxToElemList;
394 std::cout <<
" Found matching element " << i <<
".\n";
396 if (!m_checkMultipleElement)
return idxToElemList;
397 for (
int j = 0; j < 4; ++j) {
398 for (
int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
407 PrintElement(
"FindElement13", x, y, z, t1, t2, t3, t4, element, 10);
412 if (m_checkMultipleElement) {
416 std::cout <<
" No element matching point (" << x <<
", " << y <<
", "
417 << z <<
") found.\n";
424 std::cerr <<
" Found << " << nfound <<
" elements matching point ("
425 << x <<
", " << y <<
", " << z <<
").\n";
427 for (
int j = 0; j < 4; ++j) {
428 for (
int k = 0; k < 4; ++k) jac[j][k] = jacbak[j][k];
436 m_lastElement = imap;
442 std::cout <<
" No element matching point (" << x <<
", " << y <<
", "
443 << z <<
") found.\n";
449 const double z,
double& t1,
double& t2,
450 double& t3, TMatrixD*& jac,
451 std::vector<TMatrixD*>& dN) {
453 if (m_lastElement >= 0) {
456 if (x >= n3.
x && y >= n3.
y && z >= n3.
z) {
460 if (x < n0.
x && y < n2.
y && z < n7.
z) {
461 imap = m_lastElement;
469 for (
size_t i = 0; i < nElements; ++i) {
472 if (x < n3.
x || y < n3.
y || z < n3.
z)
continue;
476 if (x < n0.
x && y < n2.
y && z < n7.
z) {
485 std::cout <<
m_className <<
"::FindElementCube:\n";
486 std::cout <<
" Point (" << x <<
"," << y <<
"," << z
487 <<
") not in the mesh, it is background or PEC.\n";
492 std::cout <<
" First node (" << first3.
x <<
"," << first3.
y <<
","
493 << first3.
z <<
") in the mesh.\n";
494 std::cout <<
" dx= " << (first0.
x - first3.
x)
495 <<
", dy= " << (first2.
y - first3.
y)
496 <<
", dz= " << (first7.
z - first3.
z) <<
"\n";
502 std::cout <<
" Last node (" << last5.
x <<
"," << last5.
y <<
","
503 << last5.
z <<
") in the mesh.\n";
504 std::cout <<
" dx= " << (last0.
x - last3.
x)
505 <<
", dy= " << (last2.
y - last3.
y)
506 <<
", dz= " << (last7.
z - last3.
z) <<
"\n";
510 CoordinatesCube(x, y, z, t1, t2, t3, jac, dN,
m_elements[imap]);
518void ComponentFieldMap::Jacobian3(
const Element& element,
const double u,
519 const double v,
const double w,
double& det,
520 double jac[4][4])
const {
521 const Node& n0 =
m_nodes[element.emap[0]];
522 const Node& n1 =
m_nodes[element.emap[1]];
523 const Node& n2 =
m_nodes[element.emap[2]];
524 const Node& n3 =
m_nodes[element.emap[3]];
525 const Node& n4 =
m_nodes[element.emap[4]];
526 const Node& n5 =
m_nodes[element.emap[5]];
529 const double fouru = 4 * u;
530 const double fourv = 4 * v;
531 const double fourw = 4 * w;
533 const double ax = (-1 + fourv) * n1.x + fouru * n3.x + fourw * n5.x;
534 const double ay = (-1 + fourv) * n1.y + fouru * n3.y + fourw * n5.y;
535 const double bx = (-1 + fourw) * n2.x + fouru * n4.x + fourv * n5.x;
536 const double by = (-1 + fourw) * n2.y + fouru * n4.y + fourv * n5.y;
537 const double cx = (-1 + fouru) * n0.x + fourv * n3.x + fourw * n4.x;
538 const double cy = (-1 + fouru) * n0.y + fourv * n3.y + fourw * n4.y;
540 det = -(ax - bx) * cy - (cx - ax) * by + (cx - bx) * ay;
543 jac[0][0] = ax * by - bx * ay;
546 jac[1][0] = bx * cy - cx * by;
549 jac[2][0] = -ax * cy + cx * ay;
554void ComponentFieldMap::Jacobian5(
const Element& element,
const double u,
555 const double v,
double& det,
556 double jac[4][4])
const {
557 const Node& n0 =
m_nodes[element.emap[0]];
558 const Node& n1 =
m_nodes[element.emap[1]];
559 const Node& n2 =
m_nodes[element.emap[2]];
560 const Node& n3 =
m_nodes[element.emap[3]];
561 const Node& n4 =
m_nodes[element.emap[4]];
562 const Node& n5 =
m_nodes[element.emap[5]];
563 const Node& n6 =
m_nodes[element.emap[6]];
564 const Node& n7 =
m_nodes[element.emap[7]];
565 const double u2 = u * u;
566 const double v2 = v * v;
567 const double twou = 2 * u;
568 const double twov = 2 * v;
569 const double two0x = 2 * n0.x;
570 const double two0y = 2 * n0.y;
571 const double two1x = 2 * n1.x;
572 const double two1y = 2 * n1.y;
573 const double two2x = 2 * n2.x;
574 const double two2y = 2 * n2.y;
575 const double two3x = 2 * n3.x;
576 const double two3y = 2 * n3.y;
577 const double two4x = 2 * n4.x;
578 const double two4y = 2 * n4.y;
579 const double two5x = 2 * n5.x;
580 const double two5y = 2 * n5.y;
581 const double two6x = 2 * n6.x;
582 const double two6y = 2 * n6.y;
583 const double two7x = 2 * n7.x;
584 const double two7y = 2 * n7.y;
588 ((n2.x + n3.x - two6x) * (n0.y + n1.y - two4y) -
589 (n0.x + n1.x - two4x) * (n2.y + n3.y - two6y)) +
591 (-((n0.x + n3.x - two7x) * (n1.y + n2.y - two5y)) +
592 (n1.x + n2.x - two5x) * (n0.y + n3.y - two7y)) +
593 2 * (-((n5.x - n7.x) * (n4.y - n6.y)) + (n4.x - n6.x) * (n5.y - n7.y)) +
594 v * (-(n6.x * n0.y) - two7x * n0.y + n6.x * n1.y - two7x * n1.y -
595 n6.x * n2.y - two7x * n2.y + n4.x * (n0.y - n1.y + n2.y - n3.y) +
596 n6.x * n3.y - two7x * n3.y - n0.x * n4.y + n1.x * n4.y -
597 n2.x * n4.y + n3.x * n4.y - two0x * n5.y - two1x * n5.y -
598 two2x * n5.y - two3x * n5.y + 8 * n7.x * n5.y + n0.x * n6.y -
599 n1.x * n6.y + n2.x * n6.y - n3.x * n6.y +
600 two5x * (n0.y + n1.y + n2.y + n3.y - 4 * n7.y) +
601 2 * (n0.x + n1.x + n2.x + n3.x) * n7.y) +
602 v2 * (-(n4.x * n0.y) + two5x * n0.y + n6.x * n0.y + two7x * n0.y +
603 n4.x * n1.y - two5x * n1.y - n6.x * n1.y - two7x * n1.y +
604 n4.x * n2.y + two5x * n2.y - n6.x * n2.y + two7x * n2.y -
605 n4.x * n3.y - two5x * n3.y + n6.x * n3.y - two7x * n3.y +
606 two2x * (n1.y + n3.y) - n2.x * n4.y + two5x * n4.y - two7x * n4.y -
607 two2x * n5.y - two4x * n5.y + two6x * n5.y + n2.x * n6.y -
608 two5x * n6.y + two7x * n6.y +
609 n0.x * (two1y + two3y + n4.y - two5y - n6.y - two7y) -
610 2 * (n2.x - n4.x + n6.x) * n7.y +
611 n3.x * (-two0y - two2y + n4.y + two5y - n6.y + two7y) +
612 n1.x * (-two0y - two2y - n4.y + two5y + n6.y + two7y)) +
613 u * (n5.x * n0.y - two6x * n0.y - n7.x * n0.y - n5.x * n1.y -
614 two6x * n1.y + n7.x * n1.y + n5.x * n2.y - two6x * n2.y -
615 n7.x * n2.y - n5.x * n3.y - two6x * n3.y + n7.x * n3.y -
616 two1x * n4.y - two2x * n4.y - two3x * n4.y + 8 * n6.x * n4.y +
617 n1.x * n5.y - n2.x * n5.y + n3.x * n5.y +
618 two4x * (n0.y + n1.y + n2.y + n3.y - 4 * n6.y) + two1x * n6.y +
619 two2x * n6.y + two3x * n6.y - (n1.x - n2.x + n3.x) * n7.y +
620 n0.x * (-two4y - n5.y + two6y + n7.y) +
621 v2 * (4 * n4.x * n0.y - 3 * n5.x * n0.y - 4 * n6.x * n0.y -
622 5 * n7.x * n0.y + 4 * n4.x * n1.y - 5 * n5.x * n1.y -
623 4 * n6.x * n1.y - 3 * n7.x * n1.y + 4 * n4.x * n2.y +
624 5 * n5.x * n2.y - 4 * n6.x * n2.y + 3 * n7.x * n2.y +
625 4 * n4.x * n3.y + 3 * n5.x * n3.y - 4 * n6.x * n3.y +
626 5 * n7.x * n3.y + 8 * n5.x * n4.y + 8 * n7.x * n4.y -
627 8 * n4.x * n5.y + 8 * n6.x * n5.y - 8 * n5.x * n6.y -
629 n3.x * (5 * n0.y + 3 * n1.y - 4 * n4.y - 3 * n5.y + 4 * n6.y -
631 n2.x * (3 * n0.y + 5 * n1.y - 4 * n4.y - 5 * n5.y + 4 * n6.y -
633 8 * n4.x * n7.y + 8 * n6.x * n7.y +
634 n1.x * (-5 * n2.y - 3 * n3.y - 4 * n4.y + 5 * n5.y +
635 4 * n6.y + 3 * n7.y) +
636 n0.x * (-3 * n2.y - 5 * n3.y - 4 * n4.y + 3 * n5.y +
637 4 * n6.y + 5 * n7.y)) -
638 twov * (n6.x * n0.y - 3 * n7.x * n0.y + n6.x * n1.y - n7.x * n1.y +
639 3 * n6.x * n2.y - n7.x * n2.y + 3 * n6.x * n3.y -
640 3 * n7.x * n3.y - 3 * n0.x * n4.y - 3 * n1.x * n4.y -
641 n2.x * n4.y - n3.x * n4.y + 4 * n7.x * n4.y + n0.x * n5.y +
642 3 * n1.x * n5.y + 3 * n2.x * n5.y + n3.x * n5.y -
643 4 * n6.x * n5.y - n0.x * n6.y - n1.x * n6.y -
644 3 * n2.x * n6.y - 3 * n3.x * n6.y + 4 * n7.x * n6.y -
645 n5.x * (n0.y + 3 * n1.y + 3 * n2.y + n3.y -
647 (3 * n0.x + n1.x + n2.x + 3 * n3.x - 4 * n6.x) * n7.y +
648 n4.x * (3 * n0.y + 3 * n1.y + n2.y + n3.y -
649 4 * (n5.y + n7.y)))) +
651 (two3x * n0.y - two4x * n0.y - n5.x * n0.y - two6x * n0.y +
652 n7.x * n0.y - two0x * n1.y + two4x * n1.y - n5.x * n1.y +
653 two6x * n1.y + n7.x * n1.y + two3x * n2.y - two4x * n2.y +
654 n5.x * n2.y - two6x * n2.y - n7.x * n2.y + two4x * n3.y +
655 n5.x * n3.y + two6x * n3.y - n7.x * n3.y - two3x * n4.y +
656 two5x * n4.y - two7x * n4.y - n3.x * n5.y - two4x * n5.y +
657 two6x * n5.y - two3x * n6.y - two5x * n6.y + two7x * n6.y +
658 n0.x * (-two3y + two4y + n5.y + two6y - n7.y) +
659 (n3.x + two4x - two6x) * n7.y +
660 n2.x * (-two1y - two3y + two4y - n5.y + two6y + n7.y) -
662 (n5.x * n0.y - n6.x * n0.y - n7.x * n0.y + n5.x * n1.y +
663 n6.x * n1.y - n7.x * n1.y - n5.x * n2.y + n6.x * n2.y +
664 n7.x * n2.y - n5.x * n3.y - n6.x * n3.y + n7.x * n3.y -
665 two5x * n4.y + two7x * n4.y - two6x * n5.y + two5x * n6.y -
667 n4.x * (n0.y - n1.y - n2.y + n3.y + two5y - two7y) +
668 n3.x * (n0.y - n2.y - n4.y + n5.y + n6.y - n7.y) +
670 (n0.x - n2.x) * (n1.y - n3.y - n4.y - n5.y + n6.y + n7.y)) +
671 v * (4 * n5.x * n0.y + 3 * n6.x * n0.y - 4 * n7.x * n0.y +
672 4 * n5.x * n1.y - 3 * n6.x * n1.y - 4 * n7.x * n1.y +
673 4 * n5.x * n2.y - 5 * n6.x * n2.y - 4 * n7.x * n2.y +
674 4 * n5.x * n3.y + 5 * n6.x * n3.y - 4 * n7.x * n3.y -
675 8 * n5.x * n4.y + 8 * n7.x * n4.y + 8 * n6.x * n5.y -
676 8 * n5.x * n6.y + 8 * n7.x * n6.y +
677 n4.x * (5 * n0.y - 5 * n1.y - 3 * n2.y + 3 * n3.y + 8 * n5.y -
680 n3.x * (3 * n1.y + 5 * n2.y - 3 * n4.y - 4 * n5.y - 5 * n6.y +
682 n0.x * (5 * n1.y + 3 * n2.y - 5 * n4.y - 4 * n5.y - 3 * n6.y +
684 n2.x * (-3 * n0.y - 5 * n3.y + 3 * n4.y - 4 * n5.y + 5 * n6.y +
686 n1.x * ((-1 + v) * (-2 + 3 * v) * n0.y + two2y - two4y + n5.y -
688 v * (-3 * n3.y + 5 * n4.y - 4 * n5.y + 3 * n6.y + 4 * n7.y -
689 3 * v * (n2.y + n4.y - n5.y - n6.y + n7.y))))) /
693 (u2 * (-n0.y - n1.y + n2.y + n3.y + two4y - two6y) +
694 2 * (-n4.y + n6.y + v * (n0.y + n1.y + n2.y + n3.y - two5y - two7y)) +
695 u * (n0.y - twov * n0.y - n1.y + twov * n1.y + n2.y + twov * n2.y -
696 n3.y - twov * n3.y - twov * two5y + twov * two7y)) /
699 (u2 * (n0.x + n1.x - n2.x - n3.x - two4x + two6x) -
700 2 * (-n4.x + n6.x + v * (n0.x + n1.x + n2.x + n3.x - two5x - two7x)) +
701 u * ((-1 + twov) * n0.x + n1.x - twov * n1.x - n2.x - twov * n2.x +
702 n3.x + twov * n3.x + twov * two5x - twov * two7x)) /
705 (v * (-n0.y + n1.y - n2.y + n3.y) - two5y +
706 twou * ((-1 + v) * n0.y + (-1 + v) * n1.y - n2.y - v * n2.y - n3.y -
707 v * n3.y + two4y - twov * n4.y + two6y + twov * n6.y) +
708 v2 * (n0.y - n1.y - n2.y + n3.y + two5y - two7y) + two7y) /
711 (v * (n0.x - n1.x + n2.x - n3.x) +
712 twou * (n0.x - v * n0.x + n1.x - v * n1.x + n2.x + v * n2.x + n3.x +
713 v * n3.x - two4x + twov * n4.x - two6x - twov * n6.x) +
714 two5x - two7x + v2 * (-n0.x + n1.x + n2.x - n3.x - two5x + two7x)) /
718void ComponentFieldMap::Jacobian13(
const Element& element,
const double t,
719 const double u,
const double v,
720 const double w,
double& det,
721 double jac[4][4])
const {
722 const Node& n0 =
m_nodes[element.emap[0]];
723 const Node& n1 =
m_nodes[element.emap[1]];
724 const Node& n2 =
m_nodes[element.emap[2]];
725 const Node& n3 =
m_nodes[element.emap[3]];
726 const Node& n4 =
m_nodes[element.emap[4]];
727 const Node& n5 =
m_nodes[element.emap[5]];
728 const Node& n6 =
m_nodes[element.emap[6]];
729 const Node& n7 =
m_nodes[element.emap[7]];
730 const Node& n8 =
m_nodes[element.emap[8]];
731 const Node& n9 =
m_nodes[element.emap[9]];
734 const double fourt = 4 * t;
735 const double fouru = 4 * u;
736 const double fourv = 4 * v;
737 const double fourw = 4 * w;
739 const double x0 = (-1 + fourt) * n0.x;
740 const double y0 = (-1 + fourt) * n0.y;
741 const double z0 = (-1 + fourt) * n0.z;
742 const double xp = fouru * n4.x + fourv * n5.x + fourw * n6.x;
743 const double yp = fouru * n4.y + fourv * n5.y + fourw * n6.y;
744 const double zp = fouru * n4.z + fourv * n5.z + fourw * n6.z;
746 const double tx = x0 + xp;
747 const double ty = y0 + yp;
748 const double tz = z0 + zp;
750 const double x1 = (-1 + fouru) * n1.x;
751 const double y1 = (-1 + fouru) * n1.y;
752 const double z1 = (-1 + fouru) * n1.z;
753 const double xq = fourt * n4.x + fourv * n7.x + fourw * n8.x;
754 const double yq = fourt * n4.y + fourv * n7.y + fourw * n8.y;
755 const double zq = fourt * n4.z + fourv * n7.z + fourw * n8.z;
757 const double ux = x1 + xq;
758 const double uy = y1 + yq;
759 const double uz = z1 + zq;
761 const double x2 = (-1 + fourv) * n2.x;
762 const double y2 = (-1 + fourv) * n2.y;
763 const double z2 = (-1 + fourv) * n2.z;
764 const double xr = fourt * n5.x + fouru * n7.x + fourw * n9.x;
765 const double yr = fourt * n5.y + fouru * n7.y + fourw * n9.y;
766 const double zr = fourt * n5.z + fouru * n7.z + fourw * n9.z;
768 const double vx = x2 + xr;
769 const double vy = y2 + yr;
770 const double vz = z2 + zr;
772 const double x3 = (-1 + fourw) * n3.x;
773 const double y3 = (-1 + fourw) * n3.y;
774 const double z3 = (-1 + fourw) * n3.z;
775 const double xs = fourt * n6.x + fouru * n8.x + fourv * n9.x;
776 const double ys = fourt * n6.y + fouru * n8.y + fourv * n9.y;
777 const double zs = fourt * n6.z + fouru * n8.z + fourv * n9.z;
779 const double wx = x3 + xs;
780 const double wy = y3 + ys;
781 const double wz = z3 + zs;
783 const double ax = x1 - x3 + xq - xs;
784 const double ay = y1 - y3 + yq - ys;
786 const double bx = x1 - x2 + xq - xr;
787 const double by = y1 - y2 + yq - yr;
789 const double cx = x2 - x3 + xr - xs;
790 const double cy = y2 - y3 + yr - ys;
792 const double dx = x0 - x3 + xp - xs;
793 const double dy = y0 - y3 + yp - ys;
795 const double ex = x0 - x2 + xp - xr;
796 const double ey = y0 - y2 + yp - yr;
798 const double fx = x0 - x1 + xp - xq;
799 const double fy = y0 - y1 + yp - yq;
802 det = (-ax * vy + bx *
wy + cx * uy) * tz -
803 (-ax * ty - fx * wy + dx * uy) * vz +
804 (-bx * ty - fx * vy + ex * uy) * wz +
805 (-cx * ty + dx * vy - ex * wy) * uz;
807 const double tu = tx * uy - ux * ty;
808 const double tv = tx * vy - vx * ty;
809 const double tw = tx *
wy -
wx * ty;
810 const double uv = ux * vy - vx * uy;
811 const double uw = ux *
wy -
wx * uy;
812 const double vw = vx *
wy -
wx * vy;
814 jac[0][0] = -uw * vz + uv *
wz + vw * uz;
815 jac[1][0] = -vw * tz + tw * vz - tv *
wz;
816 jac[2][0] = uw * tz + tu *
wz - tw * uz;
817 jac[3][0] = -uv * tz - tu * vz + tv * uz;
819 jac[0][1] = -ay * vz + by *
wz + cy * uz;
820 jac[0][2] = ax * vz - bx *
wz - cx * uz;
821 jac[0][3] = -ax * vy + bx *
wy + cx * uy;
823 jac[1][1] = -cy * tz + dy * vz - ey *
wz;
824 jac[1][2] = cx * tz - dx * vz + ex *
wz;
825 jac[1][3] = -cx * ty + dx * vy - ex *
wy;
827 jac[2][1] = ay * tz + fy *
wz - dy * uz;
828 jac[2][2] = -ax * tz - fx *
wz + dx * uz;
829 jac[2][3] = ax * ty + fx *
wy - dx * uy;
831 jac[3][1] = -by * tz - fy * vz + ey * uz;
832 jac[3][2] = bx * tz + fx * vz - ex * uz;
833 jac[3][3] = -bx * ty - fx * vy + ex * uy;
836void ComponentFieldMap::JacobianCube(
const Element& element,
const double t1,
837 const double t2,
const double t3,
839 std::vector<TMatrixD*>& dN)
const {
842 std::cerr <<
" Pointer to Jacobian matrix is empty!\n";
848 double N1[3] = {-1 * (1 - t2) * (1 - t3), (1 - t1) * -1 * (1 - t3),
849 (1 - t1) * (1 - t2) * -1};
850 double N2[3] = {+1 * (1 - t2) * (1 - t3), (1 + t1) * -1 * (1 - t3),
851 (1 + t1) * (1 - t2) * -1};
852 double N3[3] = {+1 * (1 + t2) * (1 - t3), (1 + t1) * +1 * (1 - t3),
853 (1 + t1) * (1 + t2) * -1};
854 double N4[3] = {-1 * (1 + t2) * (1 - t3), (1 - t1) * +1 * (1 - t3),
855 (1 - t1) * (1 + t2) * -1};
856 double N5[3] = {-1 * (1 - t2) * (1 + t3), (1 - t1) * -1 * (1 + t3),
857 (1 - t1) * (1 - t2) * +1};
858 double N6[3] = {+1 * (1 - t2) * (1 + t3), (1 + t1) * -1 * (1 + t3),
859 (1 + t1) * (1 - t2) * +1};
860 double N7[3] = {+1 * (1 + t2) * (1 + t3), (1 + t1) * +1 * (1 + t3),
861 (1 + t1) * (1 + t2) * +1};
862 double N8[3] = {-1 * (1 + t2) * (1 + t3), (1 - t1) * +1 * (1 + t3),
863 (1 - t1) * (1 + t2) * +1};
865 TMatrixD* m_N1 =
new TMatrixD(3, 1, N1);
866 *m_N1 = (1. / 8. * (*m_N1));
868 TMatrixD* m_N2 =
new TMatrixD(3, 1, N2);
869 *m_N2 = (1. / 8. * (*m_N2));
871 TMatrixD* m_N3 =
new TMatrixD(3, 1, N3);
872 *m_N3 = (1. / 8. * (*m_N3));
874 TMatrixD* m_N4 =
new TMatrixD(3, 1, N4);
875 *m_N4 = (1. / 8. * (*m_N4));
877 TMatrixD* m_N5 =
new TMatrixD(3, 1, N5);
878 *m_N5 = (1. / 8. * (*m_N5));
880 TMatrixD* m_N6 =
new TMatrixD(3, 1, N6);
881 *m_N6 = (1. / 8. * (*m_N6));
883 TMatrixD* m_N7 =
new TMatrixD(3, 1, N7);
884 *m_N7 = (1. / 8. * (*m_N7));
886 TMatrixD* m_N8 =
new TMatrixD(3, 1, N8);
887 *m_N8 = (1. / 8. * (*m_N8));
890 for (
int j = 0; j < 8; ++j) {
891 const Node& node =
m_nodes[element.emap[j]];
892 (*jac)(0, 0) += node.x * ((*dN.at(j))(0, 0));
893 (*jac)(0, 1) += node.y * ((*dN.at(j))(0, 0));
894 (*jac)(0, 2) += node.z * ((*dN.at(j))(0, 0));
895 (*jac)(1, 0) += node.x * ((*dN.at(j))(1, 0));
896 (*jac)(1, 1) += node.y * ((*dN.at(j))(1, 0));
897 (*jac)(1, 2) += node.z * ((*dN.at(j))(1, 0));
898 (*jac)(2, 0) += node.x * ((*dN.at(j))(2, 0));
899 (*jac)(2, 1) += node.y * ((*dN.at(j))(2, 0));
900 (*jac)(2, 2) += node.z * ((*dN.at(j))(2, 0));
905 std::cout <<
m_className <<
"::JacobianCube:" << std::endl;
906 std::cout <<
" Det.: " << jac->Determinant() << std::endl;
907 std::cout <<
" Jacobian matrix.: " << std::endl;
908 jac->Print(
"%11.10g");
909 std::cout <<
" Hexahedral coordinates (t, u, v) = (" << t1 <<
"," << t2
910 <<
"," << t3 <<
")" << std::endl;
911 std::cout <<
" Node xyzV" << std::endl;
912 for (
int j = 0; j < 8; ++j) {
913 const Node& node =
m_nodes[element.emap[j]];
914 std::cout <<
" " << element.emap[j] <<
" " << node.x
915 <<
" " << node.y <<
" " << node.z <<
" "
916 << node.v << std::endl;
921int ComponentFieldMap::Coordinates3(
const double x,
const double y,
922 const double z,
double& t1,
double& t2,
923 double& t3,
double& t4,
double jac[4][4],
924 double& det,
const Element& element)
const {
927 std::cout <<
" Point (" <<
x <<
", " <<
y <<
", " <<
z <<
")\n";
931 t1 = t2 = t3 = t4 = 0;
934 const Node& n0 =
m_nodes[element.emap[0]];
935 const Node& n1 =
m_nodes[element.emap[1]];
936 const Node& n2 =
m_nodes[element.emap[2]];
938 (n0.x - n1.x) * (n2.y - n1.y) - (n2.x - n1.x) * (n0.y - n1.y);
940 (n1.x - n2.x) * (n0.y - n2.y) - (n0.x - n2.x) * (n1.y - n2.y);
942 (n2.x - n0.x) * (n1.y - n0.y) - (n1.x - n0.x) * (n2.y - n0.y);
943 if (d1 == 0 || d2 == 0 || d3 == 0) {
945 std::cerr <<
" Calculation of linear coordinates failed; abandoned.\n";
948 t1 = ((
x - n1.x) * (n2.y - n1.y) - (
y - n1.y) * (n2.x - n1.x)) / d1;
949 t2 = ((
x - n2.x) * (n0.y - n2.y) - (
y - n2.y) * (n0.x - n2.x)) / d2;
950 t3 = ((
x - n0.x) * (n1.y - n0.y) - (
y - n0.y) * (n1.x - n0.x)) / d3;
952 const Node& n3 =
m_nodes[element.emap[3]];
953 const Node& n4 =
m_nodes[element.emap[4]];
954 const Node& n5 =
m_nodes[element.emap[5]];
957 double td1 = t1, td2 = t2, td3 = t3;
958 bool converged =
false;
959 for (
int iter = 0; iter < 10; iter++) {
962 std::cout <<
" Iteration " << iter <<
": (u, v, w) = (" << td1
963 <<
", " << td2 <<
", " << td3 <<
"), sum = " << td1 + td2 + td3
967 const double f0 = td1 * (2 * td1 - 1);
968 const double f1 = td2 * (2 * td2 - 1);
969 const double f2 = td3 * (2 * td3 - 1);
970 const double f3 = 4 * td1 * td2;
971 const double f4 = 4 * td1 * td3;
972 const double f5 = 4 * td2 * td3;
975 n0.x * f0 + n1.x * f1 + n2.x * f2 + n3.x * f3 + n4.x * f4 + n5.x * f5;
977 n0.y * f0 + n1.y * f1 + n2.y * f2 + n3.y * f3 + n4.y * f4 + n5.y * f5;
978 const double sr = td1 + td2 + td3;
980 Jacobian3(element, td1, td2, td3, det, jac);
982 const double diff[3] = {1 - sr,
x - xr,
y - yr};
984 const double invdet = 1. / det;
985 double corr[3] = {0., 0., 0.};
986 for (
size_t l = 0; l < 3; l++) {
987 for (
size_t k = 0; k < 3; k++) {
988 corr[l] += jac[l][k] * diff[k];
995 std::cout <<
" Difference vector: (1, x, y) = (" << diff[0] <<
", "
996 << diff[1] <<
", " << diff[2] <<
").\n";
997 std::cout <<
" Correction vector: (u, v, w) = (" << corr[0] <<
", "
998 << corr[1] <<
", " << corr[2] <<
").\n";
1005 constexpr double tol = 1.e-5;
1006 if (
fabs(corr[0]) < tol &&
fabs(corr[1]) < tol &&
fabs(corr[2]) < tol) {
1008 std::cout <<
m_className <<
"::Coordinates3: Convergence reached.";
1016 const double xmin = std::min({n0.x, n1.x, n2.x});
1017 const double xmax = std::max({n0.x, n1.x, n2.x});
1018 const double ymin = std::min({n0.y, n1.y, n2.y});
1019 const double ymax = std::max({n0.y, n1.y, n2.y});
1020 if (x >= xmin && x <= xmax && y >= ymin && y <= ymax) {
1023 <<
" No convergence achieved "
1024 <<
"when refining internal isoparametric coordinates\n"
1025 <<
" at position (" <<
x <<
", " <<
y <<
").\n";
1027 t1 = t2 = t3 = t4 = 0;
1039 std::cout <<
" Convergence reached at (t1, t2, t3) = (" << t1 <<
", "
1040 << t2 <<
", " << t3 <<
").\n";
1042 const double f0 = td1 * (2 * td1 - 1);
1043 const double f1 = td2 * (2 * td2 - 1);
1044 const double f2 = td3 * (2 * td3 - 1);
1045 const double f3 = 4 * td1 * td2;
1046 const double f4 = 4 * td1 * td3;
1047 const double f5 = 4 * td2 * td3;
1049 n0.x * f0 + n1.x * f1 + n2.x * f2 + n3.x * f3 + n4.x * f4 + n5.x * f5;
1051 n0.y * f0 + n1.y * f1 + n2.y * f2 + n3.y * f3 + n4.y * f4 + n5.y * f5;
1052 const double sr = td1 + td2 + td3;
1054 std::cout <<
" Position requested: (" <<
x <<
", " <<
y <<
")\n";
1055 std::cout <<
" Reconstructed: (" << xr <<
", " << yr <<
")\n";
1056 std::cout <<
" Difference: (" <<
x - xr <<
", " <<
y - yr
1058 std::cout <<
" Checksum - 1: " << sr - 1 <<
"\n";
1065int ComponentFieldMap::Coordinates4(
const double x,
const double y,
1066 const double z,
double& t1,
double& t2,
1067 double& t3,
double& t4,
double& det,
1068 const Element& element)
const {
1072 std::cout <<
" Point (" <<
x <<
", " <<
y <<
", " <<
z <<
")\n";
1079 t1 = t2 = t3 = t4 = 0.;
1081 const Node& n0 =
m_nodes[element.emap[0]];
1082 const Node& n1 =
m_nodes[element.emap[1]];
1083 const Node& n2 =
m_nodes[element.emap[2]];
1084 const Node& n3 =
m_nodes[element.emap[3]];
1086 const double dd = -(n0.x * n1.y) + n3.x * n2.y - n2.x * n3.y +
1087 x * (-n0.y + n1.y - n2.y + n3.y) + n1.x * (n0.y -
y) +
1088 (n0.x + n2.x - n3.x) *
y;
1089 det = -(-((n0.x - n3.x) * (n1.y - n2.y)) + (n1.x - n2.x) * (n0.y - n3.y)) *
1090 (2 *
x * (-n0.y + n1.y + n2.y - n3.y) -
1091 (n0.x + n3.x) * (n1.y + n2.y - 2 *
y) +
1092 n1.x * (n0.y + n3.y - 2 * y) + n2.x * (n0.y + n3.y - 2 *
y)) +
1100 <<
" No solution found for isoparametric coordinates\n"
1101 <<
" because the determinant " << det <<
" is < 0.\n";
1107 double prod = ((n2.x - n3.x) * (n0.y - n1.y) - (n0.x - n1.x) * (n2.y - n3.y));
1110 ((n0.x - n1.x) * (n0.x - n1.x) + (n0.y - n1.y) * (n0.y - n1.y)) *
1111 ((n2.x - n3.x) * (n2.x - n3.x) + (n2.y - n3.y) * (n2.y - n3.y))) {
1112 t1 = (-(n3.x * n0.y) + x * n0.y + n2.x * n1.y - x * n1.y - n1.x * n2.y +
1113 x * n2.y + n0.x * n3.y - x * n3.y - n0.x * y + n1.x * y - n2.x * y +
1114 n3.x * y +
sqrt(det)) /
1117 double xp = n0.y - n1.y;
1118 double yp = n1.x - n0.x;
1119 double dn =
sqrt(xp * xp + yp * yp);
1122 <<
" Element appears to be degenerate in the 1 - 2 axis.\n";
1127 double dpoint = xp * (
x - n0.x) + yp * (y - n0.y);
1128 double dbox = xp * (n3.x - n0.x) + yp * (n3.y - n0.y);
1131 <<
" Element appears to be degenerate in the 1 - 3 axis.\n";
1134 double t = -1 + 2 * dpoint / dbox;
1135 double xt1 = n0.x + 0.5 * (t + 1) * (n3.x - n0.x);
1136 double yt1 = n0.y + 0.5 * (t + 1) * (n3.y - n0.y);
1137 double xt2 = n1.x + 0.5 * (t + 1) * (n2.x - n1.x);
1138 double yt2 = n1.y + 0.5 * (t + 1) * (n2.y - n1.y);
1139 dn = (xt1 - xt2) * (xt1 - xt2) + (yt1 - yt2) * (yt1 - yt2);
1143 <<
" Coordinate requested at convergence point of element.\n";
1146 t1 = -1 + 2 * ((
x - xt1) * (xt2 - xt1) + (
y - yt1) * (yt2 - yt1)) / dn;
1150 prod = ((n0.x - n3.x) * (n1.y - n2.y) - (n1.x - n2.x) * (n0.y - n3.y));
1153 ((n0.x - n3.x) * (n0.x - n3.x) + (n0.y - n3.y) * (n0.y - n3.y)) *
1154 ((n1.x - n2.x) * (n1.x - n2.x) + (n1.y - n2.y) * (n1.y - n2.y))) {
1155 t2 = (-(n1.x * n0.y) + x * n0.y + n0.x * n1.y - x * n1.y - n3.x * n2.y +
1156 x * n2.y + n2.x * n3.y - x * n3.y - n0.x * y + n1.x * y - n2.x * y +
1157 n3.x * y -
sqrt(det)) /
1160 double xp = n0.y - n3.y;
1161 double yp = n3.x - n0.x;
1162 double dn =
sqrt(xp * xp + yp * yp);
1165 <<
" Element appears to be degenerate in the 1 - 4 axis.\n";
1170 double dpoint = xp * (
x - n0.x) + yp * (y - n0.y);
1171 double dbox = xp * (n1.x - n0.x) + yp * (n1.y - n0.y);
1174 <<
" Element appears to be degenerate in the 1 - 2 axis.\n";
1177 double t = -1 + 2 * dpoint / dbox;
1178 double xt1 = n0.x + 0.5 * (t + 1) * (n1.x - n0.x);
1179 double yt1 = n0.y + 0.5 * (t + 1) * (n1.y - n0.y);
1180 double xt2 = n3.x + 0.5 * (t + 1) * (n2.x - n3.x);
1181 double yt2 = n3.y + 0.5 * (t + 1) * (n2.y - n3.y);
1182 dn = (xt1 - xt2) * (xt1 - xt2) + (yt1 - yt2) * (yt1 - yt2);
1186 <<
" Coordinate requested at convergence point of element.\n";
1189 t2 = -1 + 2 * ((
x - xt1) * (xt2 - xt1) + (
y - yt1) * (yt2 - yt1)) / dn;
1193 std::cout <<
" Isoparametric (u, v): (" << t1 <<
", " << t2 <<
").\n";
1195 const double f0 = (1 - t1) * (1 - t2) * 0.25;
1196 const double f1 = (1 + t1) * (1 - t2) * 0.25;
1197 const double f2 = (1 + t1) * (1 + t2) * 0.25;
1198 const double f3 = (1 - t1) * (1 + t2) * 0.25;
1199 const double xr = n0.x * f0 + n1.x * f1 + n2.x * f2 + n3.x * f3;
1200 const double yr = n0.y * f0 + n1.y * f1 + n2.y * f2 + n3.y * f3;
1202 std::cout <<
" Position requested: (" <<
x <<
", " <<
y <<
")\n";
1203 std::cout <<
" Reconstructed: (" << xr <<
", " << yr <<
")\n";
1204 std::cout <<
" Difference: (" <<
x - xr <<
", " <<
y - yr
1213int ComponentFieldMap::Coordinates5(
const double x,
const double y,
1214 const double z,
double& t1,
double& t2,
1215 double& t3,
double& t4,
double jac[4][4],
1216 double& det,
const Element& element)
const {
1220 std::cout <<
" Point (" <<
x <<
", " <<
y <<
", " <<
z <<
")\n";
1227 t1 = t2 = t3 = t4 = 0;
1230 if (element.degenerate) {
1231 std::cerr <<
m_className <<
"::Coordinates5: Degenerate element.\n";
1236 if (Coordinates4(x, y, z, t1, t2, t3, t4, det, element) > 0) {
1239 std::cout <<
" Failure to obtain linear estimate of isoparametric "
1246 constexpr double f = 0.5;
1248 if (t1 < -(1 + f) || t1 > (1 + f) || t2 < -(1 + f) || t2 > (1 + f)) {
1251 std::cout <<
" Point far outside, (t1,t2) = (" << t1 <<
", " << t2
1258 double td1 = t1, td2 = t2;
1259 const Node& n0 =
m_nodes[element.emap[0]];
1260 const Node& n1 =
m_nodes[element.emap[1]];
1261 const Node& n2 =
m_nodes[element.emap[2]];
1262 const Node& n3 =
m_nodes[element.emap[3]];
1263 const Node& n4 =
m_nodes[element.emap[4]];
1264 const Node& n5 =
m_nodes[element.emap[5]];
1265 const Node& n6 =
m_nodes[element.emap[6]];
1266 const Node& n7 =
m_nodes[element.emap[7]];
1267 bool converged =
false;
1268 for (
int iter = 0; iter < 10; iter++) {
1271 std::cout <<
" Iteration " << iter <<
": (t1, t2) = (" << td1
1272 <<
", " << td2 <<
").\n";
1275 const double r0 = (-(1 - td1) * (1 - td2) * (1 + td1 + td2)) * 0.25;
1276 const double r1 = (-(1 + td1) * (1 - td2) * (1 - td1 + td2)) * 0.25;
1277 const double r2 = (-(1 + td1) * (1 + td2) * (1 - td1 - td2)) * 0.25;
1278 const double r3 = (-(1 - td1) * (1 + td2) * (1 + td1 - td2)) * 0.25;
1279 const double r4 = (1 - td1) * (1 + td1) * (1 - td2) * 0.5;
1280 const double r5 = (1 + td1) * (1 + td2) * (1 - td2) * 0.5;
1281 const double r6 = (1 - td1) * (1 + td1) * (1 + td2) * 0.5;
1282 const double r7 = (1 - td1) * (1 + td2) * (1 - td2) * 0.5;
1283 double xr = n0.x * r0 + n1.x * r1 + n2.x * r2 + n3.x * r3 + n4.x * r4 +
1284 n5.x * r5 + n6.x * r6 + n7.x * r7;
1285 double yr = n0.y * r0 + n1.y * r1 + n2.y * r2 + n3.y * r3 + n4.y * r4 +
1286 n5.y * r5 + n6.y * r6 + n7.y * r7;
1288 Jacobian5(element, td1, td2, det, jac);
1290 double diff[2] = {
x - xr,
y - yr};
1292 double corr[2] = {0., 0.};
1293 const double invdet = 1. / det;
1294 for (
size_t l = 0; l < 2; ++l) {
1295 for (
size_t k = 0; k < 2; ++k) {
1296 corr[l] += jac[l][k] * diff[k];
1303 std::cout <<
" Difference vector: (x, y) = (" << diff[0] <<
", "
1304 << diff[1] <<
").\n";
1305 std::cout <<
" Correction vector: (t1, t2) = (" << corr[0] <<
", "
1306 << corr[1] <<
").\n";
1312 constexpr double tol = 1.e-5;
1313 if (
fabs(corr[0]) < tol &&
fabs(corr[1]) < tol) {
1315 std::cout <<
m_className <<
"::Coordinates5: Convergence reached.\n";
1323 double xmin = std::min({n0.x, n1.x, n2.x, n3.x, n4.x, n5.x, n6.x, n7.x});
1324 double xmax = std::max({n0.x, n1.x, n2.x, n3.x, n4.x, n5.x, n6.x, n7.x});
1325 double ymin = std::min({n0.y, n1.y, n2.y, n3.y, n4.y, n5.y, n6.y, n7.y});
1326 double ymax = std::max({n0.y, n1.y, n2.y, n3.y, n4.y, n5.y, n6.y, n7.y});
1327 if (x >= xmin && x <= xmax && y >= ymin && y <= ymax) {
1330 <<
" No convergence achieved "
1331 <<
"when refining internal isoparametric coordinates\n"
1332 <<
" at position (" <<
x <<
", " <<
y <<
").\n";
1346 std::cout <<
" Convergence reached at (t1, t2) = (" << t1 <<
", " << t2
1349 const double r0 = (-(1 - td1) * (1 - td2) * (1 + td1 + td2)) * 0.25;
1350 const double r1 = (-(1 + td1) * (1 - td2) * (1 - td1 + td2)) * 0.25;
1351 const double r2 = (-(1 + td1) * (1 + td2) * (1 - td1 - td2)) * 0.25;
1352 const double r3 = (-(1 - td1) * (1 + td2) * (1 + td1 - td2)) * 0.25;
1353 const double r4 = (1 - td1) * (1 + td1) * (1 - td2) * 0.5;
1354 const double r5 = (1 + td1) * (1 + td2) * (1 - td2) * 0.5;
1355 const double r6 = (1 - td1) * (1 + td1) * (1 + td2) * 0.5;
1356 const double r7 = (1 - td1) * (1 + td2) * (1 - td2) * 0.5;
1357 double xr = n0.x * r0 + n1.x * r1 + n2.x * r2 + n3.x * r3 + n4.x * r4 +
1358 n5.x * r5 + n6.x * r6 + n7.x * r7;
1359 double yr = n0.y * r0 + n1.y * r1 + n2.y * r2 + n3.y * r3 + n4.y * r4 +
1360 n5.y * r5 + n6.y * r6 + n7.y * r7;
1361 std::cout <<
" Position requested: (" <<
x <<
", " <<
y <<
")\n";
1362 std::cout <<
" Reconstructed: (" << xr <<
", " << yr <<
")\n";
1363 std::cout <<
" Difference: (" <<
x - xr <<
", " <<
y - yr
1372void ComponentFieldMap::Coordinates12(
const double x,
const double y,
1373 const double z,
double& t1,
double& t2,
1374 double& t3,
double& t4,
1375 const Element& element)
const {
1378 <<
" Point (" <<
x <<
", " <<
y <<
", " <<
z <<
").\n";
1381 const Node& n0 =
m_nodes[element.emap[0]];
1382 const Node& n1 =
m_nodes[element.emap[1]];
1383 const Node& n2 =
m_nodes[element.emap[2]];
1384 const Node& n3 =
m_nodes[element.emap[3]];
1387 (n2.y - n1.y) * (n3.z - n1.z) - (n3.y - n1.y) * (n2.z - n1.z);
1389 (n2.z - n1.z) * (n3.x - n1.x) - (n3.z - n1.z) * (n2.x - n1.x);
1391 (n2.x - n1.x) * (n3.y - n1.y) - (n3.x - n1.x) * (n2.y - n1.y);
1392 t1 = (
x - n1.x) * f1x + (y - n1.y) * f1y + (
z - n1.z) * f1z;
1393 t1 = t1 / ((n0.x - n1.x) * f1x + (n0.y - n1.y) * f1y + (n0.z - n1.z) * f1z);
1395 (n0.y - n2.y) * (n3.z - n2.z) - (n3.y - n2.y) * (n0.z - n2.z);
1397 (n0.z - n2.z) * (n3.x - n2.x) - (n3.z - n2.z) * (n0.x - n2.x);
1399 (n0.x - n2.x) * (n3.y - n2.y) - (n3.x - n2.x) * (n0.y - n2.y);
1400 t2 = (
x - n2.x) * f2x + (y - n2.y) * f2y + (
z - n2.z) * f2z;
1401 t2 = t2 / ((n1.x - n2.x) * f2x + (n1.y - n2.y) * f2y + (n1.z - n2.z) * f2z);
1403 (n0.y - n3.y) * (n1.z - n3.z) - (n1.y - n3.y) * (n0.z - n3.z);
1405 (n0.z - n3.z) * (n1.x - n3.x) - (n1.z - n3.z) * (n0.x - n3.x);
1407 (n0.x - n3.x) * (n1.y - n3.y) - (n1.x - n3.x) * (n0.y - n3.y);
1408 t3 = (
x - n3.x) * f3x + (y - n3.y) * f3y + (
z - n3.z) * f3z;
1409 t3 = t3 / ((n2.x - n3.x) * f3x + (n2.y - n3.y) * f3y + (n2.z - n3.z) * f3z);
1411 (n2.y - n0.y) * (n1.z - n0.z) - (n1.y - n0.y) * (n2.z - n0.z);
1413 (n2.z - n0.z) * (n1.x - n0.x) - (n1.z - n0.z) * (n2.x - n0.x);
1415 (n2.x - n0.x) * (n1.y - n0.y) - (n1.x - n0.x) * (n2.y - n0.y);
1416 t4 = (
x - n0.x) * f4x + (y - n0.y) * f4y + (
z - n0.z) * f4z;
1417 t4 = t4 / ((n3.x - n0.x) * f4x + (n3.y - n0.y) * f4y + (n3.z - n0.z) * f4z);
1422 std::cout <<
" Tetrahedral coordinates (t, u, v, w) = (" << t1 <<
", "
1423 << t2 <<
", " << t3 <<
", " << t4
1424 <<
") sum = " << t1 + t2 + t3 + t4 <<
".\n";
1426 const double xr = n0.x * t1 + n1.x * t2 + n2.x * t3 + n3.x * t4;
1427 const double yr = n0.y * t1 + n1.y * t2 + n2.y * t3 + n3.y * t4;
1428 const double zr = n0.z * t1 + n1.z * t2 + n2.z * t3 + n3.z * t4;
1429 const double sr = t1 + t2 + t3 + t4;
1430 std::cout <<
" Position requested: (" <<
x <<
", " <<
y <<
", " <<
z
1432 std::cout <<
" Reconstructed: (" << xr <<
", " << yr <<
", "
1434 std::cout <<
" Difference: (" <<
x - xr <<
", " <<
y - yr
1435 <<
", " <<
z - zr <<
")\n";
1436 std::cout <<
" Checksum - 1: " << sr - 1 <<
"\n";
1440int ComponentFieldMap::Coordinates13(
const double x,
const double y,
1441 const double z,
double& t1,
double& t2,
1442 double& t3,
double& t4,
double jac[4][4],
1444 const Element& element)
const {
1447 std::cout <<
" Point (" <<
x <<
", " <<
y <<
", " <<
z <<
")\n";
1451 t1 = t2 = t3 = t4 = 0.;
1454 Coordinates12(x, y, z, t1, t2, t3, t4, element);
1457 constexpr double f = 0.5;
1458 if (t1 < -f || t2 < -f || t3 < -f || t4 < -f || t1 > 1 + f || t2 > 1 + f ||
1459 t3 > 1 + f || t4 > 1 + f) {
1462 std::cout <<
" Linear isoparametric coordinates more than\n";
1463 std::cout <<
" f (" << f <<
") out of range.\n";
1469 double td1 = t1, td2 = t2, td3 = t3, td4 = t4;
1470 const Node& n0 =
m_nodes[element.emap[0]];
1471 const Node& n1 =
m_nodes[element.emap[1]];
1472 const Node& n2 =
m_nodes[element.emap[2]];
1473 const Node& n3 =
m_nodes[element.emap[3]];
1474 const Node& n4 =
m_nodes[element.emap[4]];
1475 const Node& n5 =
m_nodes[element.emap[5]];
1476 const Node& n6 =
m_nodes[element.emap[6]];
1477 const Node& n7 =
m_nodes[element.emap[7]];
1478 const Node& n8 =
m_nodes[element.emap[8]];
1479 const Node& n9 =
m_nodes[element.emap[9]];
1482 bool converged =
false;
1483 double diff[4], corr[4];
1484 for (
int iter = 0; iter < 10; iter++) {
1487 std::printf(
" Iteration %4u: t = (%15.8f, %15.8f %15.8f %15.8f)\n",
1488 iter, td1, td2, td3, td4);
1490 const double f0 = td1 * (2 * td1 - 1);
1491 const double f1 = td2 * (2 * td2 - 1);
1492 const double f2 = td3 * (2 * td3 - 1);
1493 const double f3 = td4 * (2 * td4 - 1);
1494 const double f4 = 4 * td1 * td2;
1495 const double f5 = 4 * td1 * td3;
1496 const double f6 = 4 * td1 * td4;
1497 const double f7 = 4 * td2 * td3;
1498 const double f8 = 4 * td2 * td4;
1499 const double f9 = 4 * td3 * td4;
1501 const double xr = n0.x * f0 + n1.x * f1 + n2.x * f2 + n3.x * f3 +
1502 n4.x * f4 + n5.x * f5 + n6.x * f6 + n7.x * f7 +
1503 n8.x * f8 + n9.x * f9;
1504 const double yr = n0.y * f0 + n1.y * f1 + n2.y * f2 + n3.y * f3 +
1505 n4.y * f4 + n5.y * f5 + n6.y * f6 + n7.y * f7 +
1506 n8.y * f8 + n9.y * f9;
1507 const double zr = n0.z * f0 + n1.z * f1 + n2.z * f2 + n3.z * f3 +
1508 n4.z * f4 + n5.z * f5 + n6.z * f6 + n7.z * f7 +
1509 n8.z * f8 + n9.z * f9;
1510 const double sr = td1 + td2 + td3 + td4;
1513 Jacobian13(element, td1, td2, td3, td4, det, jac);
1520 const double invdet = 1. / det;
1521 for (
int l = 0; l < 4; ++l) {
1523 for (
int k = 0; k < 4; ++k) {
1524 corr[l] += jac[l][k] * diff[k];
1532 std::cout <<
" Difference vector: (1, x, y, z) = (" << diff[0]
1533 <<
", " << diff[1] <<
", " << diff[2] <<
", " << diff[3]
1535 std::cout <<
" Correction vector: (t1,t2,t3,t4) = (" << corr[0]
1536 <<
", " << corr[1] <<
", " << corr[2] <<
", " << corr[3]
1547 constexpr double tol = 1.e-5;
1548 if (
fabs(corr[0]) < tol &&
fabs(corr[1]) < tol &&
fabs(corr[2]) < tol &&
1549 fabs(corr[3]) < tol) {
1551 std::cout <<
m_className <<
"::Coordinates13: Convergence reached.\n";
1560 const double xmin = std::min({n0.x, n1.x, n2.x, n3.x});
1561 const double xmax = std::max({n0.x, n1.x, n2.x, n3.x});
1562 const double ymin = std::min({n0.y, n1.y, n2.y, n3.y});
1563 const double ymax = std::max({n0.y, n1.y, n2.y, n3.y});
1564 const double zmin = std::min({n0.z, n1.z, n2.z, n3.z});
1565 const double zmax = std::max({n0.z, n1.z, n2.z, n3.z});
1566 if (x >= xmin && x <= xmax && y >= ymin && y <= ymax && z >= zmin &&
1570 <<
" No convergence achieved "
1571 <<
"when refining internal isoparametric coordinates\n"
1572 <<
" at position (" <<
x <<
", " <<
y <<
", " <<
z
1575 t1 = t2 = t3 = t4 = -1;
1587 std::cout <<
" Convergence reached at (t1, t2, t3, t4) = (" << t1 <<
", "
1588 << t2 <<
", " << t3 <<
", " << t4 <<
").\n";
1590 const double f0 = td1 * (2 * td1 - 1);
1591 const double f1 = td2 * (2 * td2 - 1);
1592 const double f2 = td3 * (2 * td3 - 1);
1593 const double f3 = td4 * (2 * td4 - 1);
1594 const double f4 = 4 * td1 * td2;
1595 const double f5 = 4 * td1 * td3;
1596 const double f6 = 4 * td1 * td4;
1597 const double f7 = 4 * td2 * td3;
1598 const double f8 = 4 * td2 * td4;
1599 const double f9 = 4 * td3 * td4;
1600 double xr = n0.x * f0 + n1.x * f1 + n2.x * f2 + n3.x * f3 + n4.x * f4 +
1601 n5.x * f5 + n6.x * f6 + n7.x * f7 + n8.x * f8 + n9.x * f9;
1602 double yr = n0.y * f0 + n1.y * f1 + n2.y * f2 + n3.y * f3 + n4.y * f4 +
1603 n5.y * f5 + n6.y * f6 + n7.y * f7 + n8.y * f8 + n9.y * f9;
1604 double zr = n0.z * f0 + n1.z * f1 + n2.z * f2 + n3.z * f3 + n4.z * f4 +
1605 n5.z * f5 + n6.z * f6 + n7.z * f7 + n8.z * f8 + n9.z * f9;
1606 double sr = td1 + td2 + td3 + td4;
1607 std::cout <<
" Position requested: (" <<
x <<
", " <<
y <<
", " <<
z
1609 std::cout <<
" Reconstructed: (" << xr <<
", " << yr <<
", "
1611 std::cout <<
" Difference: (" <<
x - xr <<
", " <<
y - yr
1612 <<
", " <<
z - zr <<
")\n";
1613 std::cout <<
" Checksum - 1: " << sr - 1 <<
"\n";
1620int ComponentFieldMap::CoordinatesCube(
const double x,
const double y,
1621 const double z,
double& t1,
double& t2,
1622 double& t3, TMatrixD*& jac,
1623 std::vector<TMatrixD*>& dN,
1624 const Element& element)
const {
1642 const Node& n0 =
m_nodes[element.emap[0]];
1643 const Node& n2 =
m_nodes[element.emap[2]];
1644 const Node& n3 =
m_nodes[element.emap[3]];
1645 const Node& n7 =
m_nodes[element.emap[7]];
1652 t2 = (2. * (
x - n3.x) / (n0.x - n3.x) - 1) * -1.;
1653 t1 = 2. * (
y - n3.y) / (n2.y - n3.y) - 1;
1654 t3 = 2. * (
z - n3.z) / (n7.z - n3.z) - 1;
1658 n[0] = 1. / 8 * (1 - t1) * (1 - t2) * (1 - t3);
1659 n[1] = 1. / 8 * (1 + t1) * (1 - t2) * (1 - t3);
1660 n[2] = 1. / 8 * (1 + t1) * (1 + t2) * (1 - t3);
1661 n[3] = 1. / 8 * (1 - t1) * (1 + t2) * (1 - t3);
1662 n[4] = 1. / 8 * (1 - t1) * (1 - t2) * (1 + t3);
1663 n[5] = 1. / 8 * (1 + t1) * (1 - t2) * (1 + t3);
1664 n[6] = 1. / 8 * (1 + t1) * (1 + t2) * (1 + t3);
1665 n[7] = 1. / 8 * (1 - t1) * (1 + t2) * (1 + t3);
1671 for (
int i = 0; i < 8; i++) {
1672 const Node& node =
m_nodes[element.emap[i]];
1673 xr += node.x * n[i];
1674 yr += node.y * n[i];
1675 zr += node.z * n[i];
1677 double sr = n[0] + n[1] + n[2] + n[3] + n[4] + n[5] + n[6] + n[7];
1678 std::cout <<
m_className <<
"::CoordinatesCube:\n";
1679 std::cout <<
" Position requested: (" <<
x <<
"," <<
y <<
"," <<
z
1681 std::cout <<
" Position reconstructed: (" << xr <<
"," << yr <<
"," << zr
1683 std::cout <<
" Difference: (" << (
x - xr) <<
"," << (y - yr)
1684 <<
"," << (
z - zr) <<
")\n";
1685 std::cout <<
" Hexahedral coordinates (t, u, v) = (" << t1 <<
"," << t2
1686 <<
"," << t3 <<
")\n";
1687 std::cout <<
" Checksum - 1: " << (sr - 1) <<
"\n";
1689 if (jac != 0) JacobianCube(element, t1, t2, t3, jac, dN);
1708 m_octree.reset(
nullptr);
1709 m_cacheElemBoundingBoxes =
false;
1719 <<
" Caching the bounding boxes of all elements...";
1720 CalculateElementBoundingBoxes();
1721 std::cout <<
" done.\n";
1723 InitializeTetrahedralTree();
1733 for (
size_t i = 0; i < 3; ++i) {
1736 std::cerr <<
m_className <<
"::UpdatePeriodicityCommon:\n"
1737 <<
" Both simple and mirror periodicity requested. Reset.\n";
1752 std::cerr <<
m_className <<
"::UpdatePeriodicityCommon:\n"
1753 <<
" Axial symmetry has been requested but map does not\n"
1754 <<
" cover an integral fraction of 2 pi. Reset.\n";
1765 std::cerr <<
m_className <<
"::UpdatePeriodicityCommon:\n"
1766 <<
" Only one rotational symmetry allowed; reset.\n";
1775 std::cerr <<
m_className <<
"::UpdatePeriodicityCommon:\n"
1776 <<
" Not allowed to combine rotational symmetry\n"
1777 <<
" and axial periodicity; reset.\n";
1787 std::cerr <<
m_className <<
"::UpdatePeriodicityCommon:\n"
1788 <<
" Rotational symmetry requested, \n"
1789 <<
" but x-range straddles 0; reset.\n";
1796 for (
size_t i = 0; i < 3; ++i) {
1801 for (
size_t i = 0; i < 3; ++i) {
1834 for (
size_t i = 0; i < 3; ++i) {
1854 std::cerr <<
m_className <<
"::UpdatePeriodicity2d:\n"
1855 <<
" Simple or mirror periodicity along z\n"
1856 <<
" requested for a 2d map; reset.\n";
1864 std::cerr <<
m_className <<
"::UpdatePeriodicity2d:\n"
1865 <<
" Axial symmetry has been requested \n"
1866 <<
" around x or y for a 2d map; reset.\n";
1884 std::cerr <<
m_className <<
"::SetRange: Field map not yet set.\n";
1894 for (
const auto& node :
m_nodes) {
1895 const std::array<double, 3> pos = {{node.x, node.y, node.z}};
1896 for (
unsigned int i = 0; i < 3; ++i) {
1903 if (node.y != 0 || node.z != 0) {
1904 const double ang = atan2(node.z, node.y);
1914 if (node.z != 0 || node.x != 0) {
1915 const double ang = atan2(node.x, node.z);
1925 if (node.x != 0 || node.y != 0) {
1926 const double ang = atan2(node.y, node.x);
1938 for (
unsigned int i = 0; i < 3; ++i) {
1966 std::cout <<
" Dimensions of the elementary block\n";
1972 std::cout <<
" Periodicities\n";
1973 const std::array<std::string, 3> axes = {{
"x",
"y",
"z"}};
1974 for (
unsigned int i = 0; i < 3; ++i) {
1975 std::cout <<
" " << axes[i] <<
":";
1977 std::cout <<
" simple with length " <<
m_cells[i] <<
" cm";
1980 std::cout <<
" mirror with length " <<
m_cells[i] <<
" cm";
1983 std::cout <<
" axial " << int(0.5 +
m_mapna[i]) <<
"-fold repetition";
1988 std::cout <<
" none";
1994 double& xmin,
double& ymin,
double& zmin,
1995 double& xmax,
double& ymax,
double& zmax) {
2008 double& xmin,
double& ymin,
double& zmin,
2009 double& xmax,
double& ymax,
double& zmax) {
2022 bool& xmirrored,
bool& ymirrored,
2023 bool& zmirrored,
double& rcoordinate,
2024 double& rotation)
const {
2033 if (xpos <
m_mapmin[0]) xpos += xrange;
2037 if (xnew <
m_mapmin[0]) xnew += xrange;
2038 int nx = int(floor(0.5 + (xnew - xpos) / xrange));
2039 if (nx != 2 * (nx / 2)) {
2046 const double auxr = sqrt(zpos * zpos + ypos * ypos);
2047 double auxphi = atan2(zpos, ypos);
2050 rotation = phirange * floor(0.5 + (auxphi - phim) / phirange);
2051 if (auxphi - rotation <
m_mapamin[0]) rotation -= phirange;
2052 if (auxphi - rotation >
m_mapamax[0]) rotation += phirange;
2053 auxphi = auxphi - rotation;
2054 ypos = auxr * cos(auxphi);
2055 zpos = auxr * sin(auxphi);
2062 if (ypos <
m_mapmin[1]) ypos += yrange;
2066 if (ynew <
m_mapmin[1]) ynew += yrange;
2067 int ny = int(floor(0.5 + (ynew - ypos) / yrange));
2068 if (ny != 2 * (ny / 2)) {
2075 const double auxr = sqrt(xpos * xpos + zpos * zpos);
2076 double auxphi = atan2(xpos, zpos);
2079 rotation = phirange * floor(0.5 + (auxphi - phim) / phirange);
2080 if (auxphi - rotation <
m_mapamin[1]) rotation -= phirange;
2081 if (auxphi - rotation >
m_mapamax[1]) rotation += phirange;
2082 auxphi = auxphi - rotation;
2083 zpos = auxr * cos(auxphi);
2084 xpos = auxr * sin(auxphi);
2091 if (zpos <
m_mapmin[2]) zpos += zrange;
2095 if (znew <
m_mapmin[2]) znew += zrange;
2096 int nz = int(floor(0.5 + (znew - zpos) / zrange));
2097 if (nz != 2 * (nz / 2)) {
2104 const double auxr = sqrt(ypos * ypos + xpos * xpos);
2105 double auxphi = atan2(ypos, xpos);
2108 rotation = phirange * floor(0.5 + (auxphi - phim) / phirange);
2109 if (auxphi - rotation <
m_mapamin[2]) rotation -= phirange;
2110 if (auxphi - rotation >
m_mapamax[2]) rotation += phirange;
2111 auxphi = auxphi - rotation;
2112 xpos = auxr * cos(auxphi);
2113 ypos = auxr * sin(auxphi);
2118 double zcoordinate = 0;
2120 rcoordinate = sqrt(ypos * ypos + zpos * zpos);
2123 rcoordinate = sqrt(xpos * xpos + zpos * zpos);
2126 rcoordinate = sqrt(xpos * xpos + ypos * ypos);
2139 double& xpos,
double& ypos,
double& zpos,
2140 bool& xmirrored,
bool& ymirrored,
2141 bool& zmirrored,
double& rcoordinate,
2142 double& rotation)
const {
2144 if (xmirrored) ex = -ex;
2145 if (ymirrored) ey = -ey;
2146 if (zmirrored) ez = -ez;
2151 er = sqrt(ey * ey + ez * ez);
2152 theta = atan2(ez, ey);
2154 ey = er * cos(theta);
2155 ez = er * sin(theta);
2158 er = sqrt(ez * ez + ex * ex);
2159 theta = atan2(ex, ez);
2161 ez = er * cos(theta);
2162 ex = er * sin(theta);
2165 er = sqrt(ex * ex + ey * ey);
2166 theta = atan2(ey, ex);
2168 ex = er * cos(theta);
2169 ey = er * sin(theta);
2179 if (rcoordinate <= 0) {
2185 ey = er * ypos / rcoordinate;
2186 ez = er * zpos / rcoordinate;
2190 if (rcoordinate <= 0) {
2195 ex = er * xpos / rcoordinate;
2197 ez = er * zpos / rcoordinate;
2201 if (rcoordinate <= 0) {
2206 ex = er * xpos / rcoordinate;
2207 ey = er * ypos / rcoordinate;
2214 std::transform(unit.begin(), unit.end(), unit.begin(), toupper);
2215 if (unit ==
"MUM" || unit ==
"MICRON" || unit ==
"MICROMETER") {
2217 }
else if (unit ==
"MM" || unit ==
"MILLIMETER") {
2219 }
else if (unit ==
"CM" || unit ==
"CENTIMETER") {
2221 }
else if (unit ==
"M" || unit ==
"METER") {
2244void ComponentFieldMap::CalculateElementBoundingBoxes() {
2253 const Node& n0 =
m_nodes[element.emap[0]];
2254 const Node& n1 =
m_nodes[element.emap[1]];
2255 const Node& n2 =
m_nodes[element.emap[2]];
2256 const Node& n3 =
m_nodes[element.emap[3]];
2257 element.bbMin[0] = std::min({n0.x, n1.x, n2.x, n3.x});
2258 element.bbMax[0] = std::max({n0.x, n1.x, n2.x, n3.x});
2259 element.bbMin[1] = std::min({n0.y, n1.y, n2.y, n3.y});
2260 element.bbMax[1] = std::max({n0.y, n1.y, n2.y, n3.y});
2261 element.bbMin[2] = std::min({n0.z, n1.z, n2.z, n3.z});
2262 element.bbMax[2] = std::max({n0.z, n1.z, n2.z, n3.z});
2264 constexpr float f = 0.2;
2265 const float tolx = f * (element.bbMax[0] - element.bbMin[0]);
2266 element.bbMin[0] -= tolx;
2267 element.bbMax[0] += tolx;
2268 const float toly = f * (element.bbMax[1] - element.bbMin[1]);
2269 element.bbMin[1] -= toly;
2270 element.bbMax[1] += toly;
2271 const float tolz = f * (element.bbMax[2] - element.bbMin[2]);
2272 element.bbMin[2] -= tolz;
2273 element.bbMax[2] += tolz;
2277bool ComponentFieldMap::InitializeTetrahedralTree() {
2285 std::cout <<
m_className <<
"::InitializeTetrahedralTree:\n"
2286 <<
" About to initialize the tetrahedral tree.\n";
2290 if (!m_cacheElemBoundingBoxes) CalculateElementBoundingBoxes();
2293 std::cerr <<
m_className <<
"::InitializeTetrahedralTree: Empty mesh.\n";
2298 double xmin =
m_nodes.front().x;
2299 double ymin =
m_nodes.front().y;
2300 double zmin =
m_nodes.front().z;
2304 for (
const auto& node :
m_nodes) {
2305 xmin = std::min(xmin, node.x);
2306 xmax = std::max(xmax, node.x);
2307 ymin = std::min(ymin, node.y);
2308 ymax = std::max(ymax, node.y);
2309 zmin = std::min(zmin, node.z);
2310 zmax = std::max(zmax, node.z);
2314 std::cout <<
" Bounding box:\n"
2315 << std::scientific <<
"\tx: " << xmin <<
" -> " << xmax <<
"\n"
2316 << std::scientific <<
"\ty: " << ymin <<
" -> " << ymax <<
"\n"
2317 << std::scientific <<
"\tz: " << zmin <<
" -> " << zmax <<
"\n";
2320 const double hx = 0.5 * (xmax - xmin);
2321 const double hy = 0.5 * (ymax - ymin);
2322 const double hz = 0.5 * (zmax - zmin);
2323 m_octree.reset(
new TetrahedralTree(Vec3(xmin + hx, ymin + hy, zmin + hz),
2326 if (
m_debug) std::cout <<
" Tree instantiated.\n";
2329 for (
unsigned int i = 0; i <
m_nodes.size(); i++) {
2331 m_octree->InsertMeshNode(Vec3(n.x, n.y, n.z), i);
2334 if (
m_debug) std::cout <<
" Tree nodes initialized successfully.\n";
2337 for (
unsigned int i = 0; i <
m_elements.size(); i++) {
2339 const double bb[6] = {e.bbMin[0], e.bbMin[1], e.bbMin[2],
2340 e.bbMax[0], e.bbMax[1], e.bbMax[2]};
2341 m_octree->InsertMeshElement(bb, i);
2344 std::cout <<
m_className <<
"::InitializeTetrahedralTree: Success.\n";
2349 const std::string& label)
const {
2350 const size_t nWeightingFields =
m_wfields.size();
2351 for (
size_t i = 0; i < nWeightingFields; ++i) {
2354 return nWeightingFields;
2358 const std::string& label) {
2360 size_t nWeightingFields =
m_wfields.size();
2361 for (
size_t i = 0; i < nWeightingFields; ++i) {
2368 node.w.resize(nWeightingFields);
2369 node.dw.resize(nWeightingFields);
2372 return nWeightingFields - 1;
2378 std::cerr <<
m_className <<
"::" << header <<
":\n"
2379 <<
" Warnings have been issued for this field map.\n";
2384 std::cerr <<
m_className <<
"::" << header <<
":\n"
2385 <<
" Field map not yet initialised.\n";
2389 const std::string& filename)
const {
2390 std::cerr <<
m_className <<
"::" << header <<
":\n"
2391 <<
" Could not open file " << filename <<
" for reading.\n"
2392 <<
" The file perhaps does not exist.\n";
2396 const double y,
const double z,
2397 const double t1,
const double t2,
2398 const double t3,
const double t4,
2400 const unsigned int n,
const int iw)
const {
2401 std::cout <<
m_className <<
"::" << header <<
":\n"
2402 <<
" Global = (" << x <<
", " << y <<
", " << z <<
")\n"
2403 <<
" Local = (" << t1 <<
", " << t2 <<
", " << t3 <<
", " << t4
2405 if (element.
degenerate) std::cout <<
" Element is degenerate.\n";
2406 std::cout <<
" Node x y z V\n";
2407 for (
unsigned int ii = 0; ii < n; ++ii) {
2409 const double v = iw < 0 ? node.
v : node.
w[iw];
2410 printf(
" %-5d %12g %12g %12g %12g\n", element.
emap[ii], node.
x, node.
y,
void DriftMedium(const unsigned int imat)
Flag a field map material as a drift medium.
virtual bool GetNode(const size_t i, double &x, double &y, double &z) const
void PrintRange()
Show x, y, z, V and angular ranges.
virtual double GetElementVolume(const unsigned int i)=0
void SetMedium(const unsigned int imat, Medium *medium)
Associate a field map material with a Medium class.
void PrintMaterials()
List all currently defined materials.
bool SetDefaultDriftMedium()
Find lowest epsilon, check for eps = 0, set default drift media flags.
std::array< double, 3 > m_mapamin
double ReadDouble(char *token, double def, bool &error)
void MapCoordinates(double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (xpos, ypos, zpos) to field map coordinates.
void PrintWarning(const std::string &header)
virtual void GetAspectRatio(const unsigned int i, double &dmin, double &dmax)=0
std::array< double, 3 > m_maxBoundingBox
std::array< double, 3 > m_mapmin
std::array< double, 3 > m_minBoundingBox
static double ScalingFactor(std::string unit)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
void UpdatePeriodicityCommon()
int ReadInteger(char *token, int def, bool &error)
std::vector< Material > m_materials
int FindElementCube(const double x, const double y, const double z, double &t1, double &t2, double &t3, TMatrixD *&jac, std::vector< TMatrixD * > &dN)
Find the element for a point in a cube.
std::vector< bool > m_wfieldsOk
virtual ~ComponentFieldMap()
Destructor.
size_t GetWeightingFieldIndex(const std::string &label) const
bool m_printConvergenceWarnings
std::array< double, 3 > m_mapna
double GetConductivity(const unsigned int imat) const
Return the conductivity of a field map material.
ComponentFieldMap()=delete
Default constructor.
std::vector< Node > m_nodes
void PrintCouldNotOpen(const std::string &header, const std::string &filename) const
int FindElement5(const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
Find the element for a point in curved quadratic quadrilaterals.
double GetPermittivity(const unsigned int imat) const
Return the permittivity of a field map material.
void UpdatePeriodicity2d()
std::vector< std::string > m_wfields
int FindElement13(const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
Find the element for a point in curved quadratic tetrahedra.
bool GetElementaryCell(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the coordinates of the elementary cell.
std::vector< Element > m_elements
Medium * GetMedium(const unsigned int i) const
Return the Medium associated to a field map material.
void NotDriftMedium(const unsigned int imat)
Flag a field map materials as a non-drift medium.
std::array< double, 3 > m_mapamax
void PrintElement(const std::string &header, const double x, const double y, const double z, const double t1, const double t2, const double t3, const double t4, const Element &element, const unsigned int n, const int iw=-1) const
std::array< double, 3 > m_cells
std::array< bool, 3 > m_setang
virtual void SetRange()
Calculate x, y, z, V and angular ranges.
bool GetElement(const size_t i, double &vol, double &dmin, double &dmax)
Return the volume and aspect ratio of a mesh element.
std::array< double, 3 > m_mapmax
void Reset() override
Reset the component.
void UnmapFields(double &ex, double &ey, double &ez, double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (ex, ey, ez) to global coordinates.
void PrintNotReady(const std::string &header) const
size_t GetOrCreateWeightingFieldIndex(const std::string &label)
Abstract base class for components.
virtual void UpdatePeriodicity()=0
Verify periodicities.
std::array< bool, 3 > m_rotationSymmetric
Rotation symmetry around x-axis, y-axis, z-axis.
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.
bool m_debug
Switch on/off debugging messages.
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
std::string m_className
Class name.
bool m_ready
Ready for use?
std::array< bool, 3 > m_axiallyPeriodic
Axial periodicity in x, y, z.
Abstract base class for media.
const std::string & GetName() const
Get the medium name/identifier.
DoubleAc fabs(const DoubleAc &f)
DoubleAc sqrt(const DoubleAc &f)
std::array< float, 3 > bbMax
std::array< float, 3 > bbMin