393 std::unordered_map<Node *, unsigned int> poly_node_to_id;
397 const auto & [side, inward_normal, node_map] = this->
_sidelinks_data[s];
399 for (
auto t :
make_range(side->n_subtriangles()))
403 const std::array<int, 3> subtri = side->subtriangle(t);
410 libmesh_assert_less(
side_id, node_map.size());
411 const unsigned int local_id = node_map[
side_id];
415 libmesh_assert_equal_to(*(
const Point*)poly_node,
416 *(
const Point*)surf_node);
418 surf_node = surface.
add_point(*poly_node, local_id);
422 const int tri_node = inward_normal ? i : 2-i;
434 auto verify_surface = [& surface] ()
436 for (
const Elem * elem : surface.element_ptr_range())
442 libmesh_assert_equal_to(neigh,
445 libmesh_assert_less(ns, 3);
446 libmesh_assert_equal_to(elem->node_ptr(s),
448 libmesh_assert_equal_to(elem->node_ptr((s+1)%3),
461#ifdef LIBMESH_ENABLE_EXCEPTIONS
466 std::vector<std::vector<dof_id_type>> nodes_to_elem_vec_map;
472 std::vector<std::set<dof_id_type>> nodes_to_elem_map;
474 nodes_to_elem_map.emplace_back
475 (nodes_to_elem_vec_map[i].begin(),
476 nodes_to_elem_vec_map[i].end());
485 auto surroundings_of =
486 [&nodes_to_elem_map, & surface]
488 std::vector<Elem *> * surrounding_elems)
490 const std::set<dof_id_type> & elems_by_node =
491 nodes_to_elem_map[node.id()];
493 const unsigned int n_surrounding = elems_by_node.size();
494 libmesh_assert_greater_equal(n_surrounding, 3);
496 if (surrounding_elems)
499 surrounding_elems->resize(n_surrounding);
502 std::vector<Node *> surrounding_nodes(n_surrounding);
510 surrounding_nodes[i] = next_node;
511 if (surrounding_elems)
512 (*surrounding_elems)[i] = elem;
515 libmesh_assert_equal_to(elem, surface.
elem_ptr(elem->
id()));
520 libmesh_assert_equal_to
521 (std::count(surrounding_nodes.begin(),
522 surrounding_nodes.end(), next_node),
528 libmesh_assert_equal_to
529 (elem, surface.
elem_ptr(*elems_by_node.begin()));
531 return surrounding_nodes;
534 auto geometry_at = [&surroundings_of](
const Node & node)
536 const std::vector<Node *> surrounding_nodes =
537 surroundings_of(node,
nullptr);
541 Real total_solid_angle = 0;
542 const int n_surrounding =
543 cast_int<int>(surrounding_nodes.size());
548 v01 =
static_cast<Point>(*surrounding_nodes[n]) - node,
549 v02 =
static_cast<Point>(*surrounding_nodes[n+1]) - node,
550 v03 =
static_cast<Point>(*surrounding_nodes[n+2]) - node;
555 return std::make_pair(n_surrounding, total_solid_angle);
567 typedef std::multimap<std::pair<int, Real>,
Node*> node_map_type;
568 node_map_type nodes_by_geometry;
569 std::map<Node *, node_map_type::iterator> node_index;
571 for (
auto node : surface.node_ptr_range())
573 nodes_by_geometry.emplace(geometry_at(*node), node);
581 for (
auto i :
make_range(nodes_by_geometry.size()-3))
583 auto geometry_it = nodes_by_geometry.begin();
584 auto geometry_key = geometry_it->first;
585 auto [valence, angle] = geometry_key;
586 Node * node = geometry_it->second;
594 nodes_by_geometry.upper_bound
595 (std::make_pair(valence,
Real(100)));
598 std::tie(geometry_key, node) = *geometry_it;
599 std::tie(valence, angle) = geometry_key;
602 std::vector<Elem *> surrounding_elems;
603 std::vector<Node *> surrounding_nodes =
604 surroundings_of(*node, &surrounding_elems);
606 const std::size_t n_surrounding = surrounding_nodes.size();
611 auto find_valid_nodes_around =
612 [n_surrounding, & surrounding_nodes]
615 unsigned int jnext = (j+1)%n_surrounding;
616 while (!surrounding_nodes[jnext])
617 jnext = (jnext+1)%n_surrounding;
619 unsigned int jprev = (j+n_surrounding-1)%n_surrounding;
620 while (!surrounding_nodes[jprev])
621 jprev = (jprev+n_surrounding-1)%n_surrounding;
623 return std::make_pair(jprev, jnext);
635 std::vector<Real> local_tet_quality(n_surrounding, 1);
653 auto find_new_tet_nodes =
654 [& local_tet_quality, & find_valid_nodes_around]
657 unsigned int jbest = 0;
658 auto [jminus, jplus] = find_valid_nodes_around(jbest);
659 Real qneighbest = std::min(local_tet_quality[jminus],
660 local_tet_quality[jplus]);
662 local_tet_quality.size()))
665 if (local_tet_quality[j] <= 0)
668 std::tie(jminus, jplus) = find_valid_nodes_around(j);
669 Real qneighj = std::min(local_tet_quality[jminus],
670 local_tet_quality[jplus]);
674 if (qneighbest <= 0 &&
679 if ((local_tet_quality[j] - qneighj) >
680 (local_tet_quality[jbest] - qneighj))
683 qneighbest = qneighj;
688 (local_tet_quality[jbest] <= 0,
689 "Cannot build non-singular non-inverted tet");
691 std::tie(jminus, jplus) = find_valid_nodes_around(jbest);
693 return std::make_tuple(jbest, jminus, jplus);
696 if (n_surrounding > 3)
701 constexpr Real far_node = -1e6;
706 std::vector<Point> v0s(n_surrounding);
708 v0s[j] = *(
Point *)surrounding_nodes[j] - *node;
712 auto local_tet_quality_of =
713 [& surrounding_nodes, & v0s, & find_valid_nodes_around]
716 auto [jminus, jplus] = find_valid_nodes_around(j);
722 const Real total_len =
723 v0s[j].norm() + v0s[jminus].norm() + v0s[jplus].norm() +
724 (*(
Point *)surrounding_nodes[jplus] -
725 *(
Point *)surrounding_nodes[j]).norm() +
726 (*(
Point *)surrounding_nodes[j] -
727 *(
Point *)surrounding_nodes[jminus]).norm() +
728 (*(
Point *)surrounding_nodes[jminus] -
729 *(
Point *)surrounding_nodes[jplus]).norm();
736 return six_vol / (total_len * total_len * total_len);
740 local_tet_quality[j] = local_tet_quality_of(j);
749 auto [jbest, jminus, jplus] = find_new_tet_nodes();
752 Node * nbest = surrounding_nodes[jbest],
753 * nminus = surrounding_nodes[jminus],
754 * nplus = surrounding_nodes[jplus];
755 this->
add_tet(nminus->id(), nbest->
id(), nplus->id(),
760 Elem * oldtri1 = surrounding_elems[jminus],
761 * oldtri2 = surrounding_elems[jbest],
766 c2 = oldtri2->get_node_index(node);
768 newtri1->set_node(0, node);
769 newtri1->set_node(1, nminus);
770 newtri1->set_node(2, nplus);
772 surrounding_elems[jminus] = newtri1;
778 newtri1->set_neighbor(1, newtri2);
779 newtri1->set_neighbor(2, neigh12);
782 newtri2->set_node(0, nplus);
783 newtri2->set_node(1, nminus);
784 newtri2->set_node(2, nbest);
789 newtri2->set_neighbor(1, neigh21);
791 newtri2->set_neighbor(2, neigh22);
796 nodes_to_elem_map[oldtri1->
node_id(p)].erase(oldtri1->
id());
797 nodes_to_elem_map[oldtri2->node_id(p)].erase(oldtri2->id());
798 nodes_to_elem_map[newtri1->node_id(p)].insert(newtri1->id());
799 nodes_to_elem_map[newtri2->node_id(p)].insert(newtri2->id());
809 Node * & nbestref = surrounding_nodes[jbest];
810 nodes_by_geometry.erase(node_index[nbestref]);
811 node_index[nbestref] =
812 nodes_by_geometry.emplace(geometry_at(*nbestref), nbestref);
817 local_tet_quality[jbest] = far_node;
823 local_tet_quality[jminus] =
824 local_tet_quality_of(jminus);
826 local_tet_quality[jplus] =
827 local_tet_quality_of(jplus);
835 auto [j2, j1, j3] = find_new_tet_nodes();
838 Node * n1 = surrounding_nodes[j1],
839 * n2 = surrounding_nodes[j2],
840 * n3 = surrounding_nodes[j3];
841 this->
add_tet(n1->
id(), n2->id(), n3->id(), node->
id());
845 Elem * oldtri1 = surrounding_elems[j1],
846 * oldtri2 = surrounding_elems[j2],
847 * oldtri3 = surrounding_elems[j3],
851 c2 = oldtri2->get_node_index(node),
852 c3 = oldtri3->get_node_index(node);
854 newtri->set_node(0, n1);
855 newtri->set_node(1, n2);
856 newtri->set_node(2, n3);
869 nodes_to_elem_map[oldtri1->
node_id(p)].erase(oldtri1->
id());
870 nodes_to_elem_map[oldtri2->node_id(p)].erase(oldtri2->id());
871 nodes_to_elem_map[oldtri3->node_id(p)].erase(oldtri3->id());
872 nodes_to_elem_map[newtri->node_id(p)].insert(newtri->id());
884 surrounding_nodes[j1] =
nullptr;
885 surrounding_nodes[j2] =
nullptr;
886 surrounding_nodes[j3] =
nullptr;
888 for (
auto ltq : surrounding_nodes)
894 for (
const Elem * elem : surface.element_ptr_range())
896 libmesh_assert_not_equal_to
897 (elem->node_ptr(p), node);
902 nodes_by_geometry.erase(geometry_it);
905 libmesh_assert_equal_to(surface.
n_elem(), 2);
922 Node * mid_elem_node =
new Node(v_avg);
935 const auto & [side, inward_normal, node_map] = this->
_sidelinks_data[s];
937 for (
auto t :
make_range(side->n_subtriangles()))
940 const auto & n1 = node_map[side->subtriangle(t)[0]];
941 const auto & n2 = node_map[side->subtriangle(t)[1]];
942 const auto & n3 = node_map[side->subtriangle(t)[2]];