998 Range *fixed_edges,
Range *corner_nodes,
const double geometry_tol,
999 const double close_tol,
const int verb,
const bool debug) {
1001 moab::Interface &moab = m_field.
get_moab();
1002 Skinner skin(&moab);
1005 auto get_ent_adj = [&moab](
const EntityHandle v,
const int dim) {
1008 CHKERR moab.get_adjacencies(&
v, 1, dim,
true,
a);
1012 auto get_adj = [&moab](
const Range r,
const int dim) {
1015 CHKERR moab.get_adjacencies(r, dim,
false,
a, moab::Interface::UNION);
1017 CHKERR moab.get_connectivity(r,
a,
true);
1021 auto get_skin = [&skin](
const auto r) {
1023 CHKERR skin.find_skin(0, r,
false, s);
1028 auto get_range = [](std::vector<EntityHandle>
v) {
1030 r.insert_list(
v.begin(),
v.end());
1034 auto get_coords = [&](
const auto v) {
1036 CHKERR moab.get_coords(&
v, 1, &coords[0]);
1041 CHKERR moab.tag_get_handle(
"DIST_SURFACE_NORMAL_VECTOR", th_normal_dist);
1045 CHKERR moab.tag_get_data(th_normal_dist, &
v, 1, &*dist_vec.begin());
1050 const double geometry_tol) {
1051 auto get_tuple = [](
const EntityHandle e,
const double dist,
1052 const double l) {
return std::make_tuple(e, dist,
l); };
1054 std::tuple<EntityHandle, double, double> min_tuple{0, 0, 0};
1056 for (
auto e : edges) {
1060 auto get_dist = [&](
auto eit) {
1063 CHKERR moab.get_connectivity(eit->first, conn, num_nodes,
true);
1065 return eit->second.dIst;
1066 else if (conn[1] ==
v)
1067 return (eit->second.lEngth - eit->second.dIst);
1072 const auto d = get_dist(eit);
1073 if (std::get<0>(min_tuple) == 0) {
1074 min_tuple = get_tuple(e, d, eit->second.lEngth);
1075 }
else if (std::get<1>(min_tuple) > d) {
1076 min_tuple = get_tuple(e, d, eit->second.lEngth);
1081 const auto geom_dist_vec = get_normal_dits(
v);
1082 const auto geom_tol = norm_2(geom_dist_vec);
1083 const auto l = std::get<2>(min_tuple);
1085 if (geom_tol <
l * geometry_tol) {
1086 return std::make_pair(get_coords(
v),
l);
1089 const auto &d =
edgesToCut.at(std::get<0>(min_tuple));
1090 return std::make_pair(
VectorDouble3(d.rayPoint + d.dIst * d.unitRayDir),
1095 auto get_in_range = [](
auto v,
auto &r) {
return (r.find(
v) != r.end()); };
1097 auto project_nodes = [&](
auto nodes_to_check) {
1101 auto get_fix_e = [](
auto fixed_edges) {
1103 return *fixed_edges;
1108 const auto fix_e = get_fix_e(fixed_edges);
1110 const auto cut_fix = intersect(
cutEdges, fix_e);
1111 const auto cut_skin = intersect(
cutEdges, skin_e);
1115 corner_n = intersect(*corner_nodes, nodes_to_check);
1116 auto fixe_n = intersect(get_adj(fix_e, 0), nodes_to_check);
1117 auto skin_n = intersect(get_adj(skin_e, 0), nodes_to_check);
1119 std::vector<std::pair<EntityHandle, TreeData>> vertices_on_cut_edges;
1120 vertices_on_cut_edges.reserve(nodes_to_check.size());
1122 auto add_zero_vertex = [&](
const EntityHandle v,
auto &&new_pos) {
1123 auto coords = get_coords(
v);
1124 auto ray = new_pos - coords;
1125 auto l = norm_2(ray);
1128 if (
l > std::numeric_limits<double>::epsilon()) {
1135 return std::make_pair(
v, data);
1138 auto intersect_v = [&](
const auto v,
const auto r) {
1139 return intersect(r, get_ent_adj(
v, 1));
1142 for (
auto v : nodes_to_check) {
1144 const auto e = intersect_v(
v,
cutEdges);
1147 if (get_in_range(
v, corner_n)) {
1148 auto p = get_prj_point(
v, e, 0);
1149 if (norm_2(get_coords(
v) - p.first) < close_tol * p.second) {
1150 vertices_on_cut_edges.push_back(add_zero_vertex(
v, get_coords(
v)));
1154 }
else if (get_in_range(
v, fixe_n)) {
1155 const auto b = intersect_v(
v, cut_fix);
1157 auto p = get_prj_point(
v, b, geometry_tol);
1158 if (norm_2(get_coords(
v) - p.first) < close_tol * p.second) {
1159 vertices_on_cut_edges.push_back(add_zero_vertex(
v, p.first));
1163 }
else if (get_in_range(
v, skin_n)) {
1164 const auto b = intersect_v(
v, cut_skin);
1166 auto p = get_prj_point(
v, b, geometry_tol);
1167 if (norm_2(get_coords(
v) - p.first) < close_tol * p.second) {
1168 vertices_on_cut_edges.push_back(add_zero_vertex(
v, p.first));
1176 auto p = get_prj_point(
v, e, geometry_tol);
1177 if (norm_2(get_coords(
v) - p.first) < close_tol * p.second) {
1178 if (get_in_range(
v, fixe_n) || get_in_range(
v, skin_n))
1179 vertices_on_cut_edges.push_back(add_zero_vertex(
v, get_coords(
v)));
1181 vertices_on_cut_edges.push_back(add_zero_vertex(
v, p.first));
1187 auto get_distances = [&](
auto &data) {
1188 std::map<EntityHandle, double> dist_map;
1189 if (!data.empty()) {
1191 CHKERR moab.tag_get_handle(
"DIST_SURFACE_NORMAL_SIGNED",
th);
1193 std::vector<EntityHandle> verts;
1194 verts.reserve(data.size());
1196 verts.emplace_back(d.first);
1197 std::vector<double> distances(verts.size());
1198 CHKERR moab.tag_get_data(
th, &*verts.begin(), verts.size(),
1199 &*distances.begin());
1200 for (
size_t i = 0;
i != verts.size(); ++
i)
1201 dist_map[verts[
i]] = distances[
i];
1206 auto dist_map = get_distances(vertices_on_cut_edges);
1207 if (!dist_map.empty()) {
1208 auto cmp = [&dist_map](
const auto &
a,
const auto &b) {
1209 return dist_map[
a.first] < dist_map[b.first];
1211 std::sort(vertices_on_cut_edges.begin(), vertices_on_cut_edges.end(),
1215 return vertices_on_cut_edges;
1218 auto get_min_quality =
1219 [&](
const Range &adj_tets,
1220 const map<EntityHandle, TreeData> &vertices_on_cut_edges,
1221 const std::pair<EntityHandle, TreeData> *test_data_ptr) {
1223 for (
auto t : adj_tets) {
1228 CHKERR moab.get_coords(conn, num_nodes, &coords[0]);
1230 auto set_new_coord = [](
auto d) {
1231 return d.rayPoint + d.dIst * d.unitRayDir;
1234 for (
auto n : {0, 1, 2, 3}) {
1236 if (test_data_ptr) {
1237 if (test_data_ptr->first == conn[
n]) {
1238 noalias(n_coords) = set_new_coord(test_data_ptr->second);
1241 auto mit = vertices_on_cut_edges.find(conn[
n]);
1242 if (mit != vertices_on_cut_edges.end()) {
1243 noalias(n_coords) = set_new_coord(mit->second);
1251 auto get_zero_distance_verts = [&](
const auto &&vertices_on_cut_edges) {
1252 std::vector<EntityHandle> zero_dist_vec;
1253 zero_dist_vec.reserve(vertices_on_cut_edges.size());
1254 for (
auto t : vertices_on_cut_edges) {
1256 auto adj_tet = intersect(
vOlume, get_ent_adj(
t.first, 3));
1261 zero_dist_vec.push_back(
t.first);
1264 return zero_dist_vec;
1269 auto get_zero_distant_ents = [&](
auto bridge_ents,
const int dim,
1270 const int bridge_dim) {
1272 intersect(get_adj(bridge_ents, dim), get_adj(vol_cut_ents, dim));
1273 auto ents_to_remove =
1274 get_adj(subtract(get_adj(ents, bridge_dim), bridge_ents), dim);
1275 return subtract(ents, ents_to_remove);
1281 get_range(get_zero_distance_verts(project_nodes(get_adj(
cutEdges, 0)))));
1291 auto adj_edges = get_ent_adj(f, 1);
1292 for (
auto e : adj_edges) {
1487 const double tol_trim_close,
1490 moab::Interface &moab = m_field.
get_moab();
1494 Skinner skin(&moab);
1500 Range tets_skin_verts;
1501 CHKERR moab.get_connectivity(tets_skin, tets_skin_verts,
true);
1503 Range tets_skin_edges;
1504 CHKERR moab.get_adjacencies(tets_skin, 1,
false, tets_skin_edges,
1505 moab::Interface::UNION);
1508 Range cut_surface_edges;
1510 moab::Interface::UNION);
1511 Range cut_surface_verts;
1516 corners = *corner_nodes;
1520 fix_edges = *fixed_edges;
1522 Range fixed_edges_verts;
1524 CHKERR moab.get_connectivity(*fixed_edges, fixed_edges_verts,
true);
1530 surface_skin =
fRont;
1535 CHKERR moab.tag_get_data(
th, &
v, 1, &point[0]);
1537 CHKERR moab.get_coords(&
v, 1, &point[0]);
1546 : d(d),
v(
v), e(e) {}
1549 typedef multi_index_container<
1552 ordered_non_unique<member<VertMap, const double, &VertMap::d>>,
1553 ordered_non_unique<member<VertMap, const EntityHandle, &VertMap::v>>,
1554 ordered_non_unique<member<VertMap, const EntityHandle, &VertMap::e>>
1559 VertMapMultiIndex verts_map;
1562 const double dist) {
1563 verts_map.insert(VertMap(dist,
v, e));
1572 auto cut_this_edge = [&](
const EntityHandle e,
const double length,
auto &ray,
1579 for (
int ii = 0; ii != 3; ++ii)
1581 for (
int ii = 0; ii != 3; ++ii)
1591 auto get_tag_data = [&](
auto th,
auto conn) {
1593 CHKERR moab.tag_get_data(
th, &conn, 1, &
t(0));
1597 double max_edge_length = 0;
1600 if (!
fRont.empty()) {
1602 treeSurfPtr = boost::shared_ptr<OrientedBoxTreeTool>(
1603 new OrientedBoxTreeTool(&moab,
"ROOTSETSURF",
true));
1606 for (
auto s : surface_skin) {
1608 auto project_on_surface = [&](
auto &
t) {
1618 t_normal(
i) /= sqrt(t_normal(
i) * t_normal(
i));
1619 const double dot = t_normal(
i) * (t_p(
i) -
t(
i));
1620 t_p(
i) =
t(
i) + dot * t_normal(
i);
1626 CHKERR moab.get_connectivity(s, conn, num_nodes,
true);
1629 CHKERR moab.get_coords(conn, num_nodes, &coords_front[0]);
1636 auto t_p_f0 = project_on_surface(t_f0);
1637 auto t_p_f1 = project_on_surface(t_f1);
1639 CHKERR moab.set_coords(&conn[0], 1, &t_p_f0(0));
1640 CHKERR moab.set_coords(&conn[1], 1, &t_p_f1(0));
1648 Tag th_dist_front_vec;
1649 CHKERR moab.tag_get_handle(
"DIST_FRONT_VECTOR", th_dist_front_vec);
1652 for (
auto e : cut_surface_edges) {
1654 auto get_conn_edge = [&moab](
auto e) {
1658 CHKERR moab.get_connectivity(e, conn_edge, num_nodes,
true);
1662 auto get_coords_edge = [&moab](
auto conn_edge) {
1663 std::array<double, 6> coords_edge;
1664 CHKERR moab.get_coords(conn_edge, 2, coords_edge.data());
1668 auto get_ftensor_coords = [](
const double *ptr) {
1672 auto conn_edge = get_conn_edge(e);
1673 auto coords_edge = get_coords_edge(conn_edge);
1675 auto t_dist0 = get_tag_data(th_dist_front_vec, conn_edge[0]);
1676 auto t_dist1 = get_tag_data(th_dist_front_vec, conn_edge[1]);
1677 auto t_e0 = get_ftensor_coords(&coords_edge[0]);
1678 auto t_e1 = get_ftensor_coords(&coords_edge[3]);
1681 t_edge_delta(
i) = t_e1(
i) - t_e0(
i);
1682 const double edge_length2 = t_edge_delta(
i) * t_edge_delta(
i);
1683 const double edge_length = sqrt(edge_length2);
1684 if (edge_length == 0)
1687 auto add_edge = [&](
auto t_cut) {
1690 t_ray(
i) = t_cut * t_edge_delta(
i);
1691 add_vert(conn_edge[0], e, fabs(t_cut));
1692 add_vert(conn_edge[1], e, fabs(t_cut - 1));
1693 cut_this_edge(e, edge_length, t_ray, t_e0);
1696 t_edge_point(
i) = t_e0(
i) + t_cut * t_edge_delta(
i);
1697 t_ray(
i) = t_edge_point(
i) - t_e1(
i);
1698 add_vert(conn_edge[0], e, fabs(t_cut));
1699 add_vert(conn_edge[1], e, fabs(t_cut - 1));
1700 cut_this_edge(e, edge_length, t_ray, t_e1);
1702 max_edge_length = std::max(max_edge_length, edge_length);
1705 auto trim_cross_edges = [&]() {
1706 if (std::min(t_dist0(
i) * t_dist0(
i), t_dist1(
i) * t_dist1(
i)) <
1709 auto make_pair = [&](
const double d,
const double te) {
1710 return std::make_pair(d, te);
1713 auto min_pair = make_pair(-1, -1);
1715 for (
auto f : surface_skin) {
1717 auto conn_front = get_conn_edge(f);
1718 auto coords_front = get_coords_edge(conn_front);
1719 auto t_f0 = get_ftensor_coords(&coords_front[0]);
1720 auto t_f1 = get_ftensor_coords(&coords_front[3]);
1726 &t_e0(0), &t_e1(0), &t_f0(0), &t_f1(0), &te, &tf);
1730 auto check = [](
auto v) {
1731 return (
v > -std::numeric_limits<double>::epsilon() &&
1732 (
v - 1) < std::numeric_limits<double>::epsilon());
1735 if (check(te) && check(tf)) {
1738 t_delta(
i) = (t_e0(
i) + te * t_edge_delta(
i)) -
1739 (t_f0(0) + tf * (t_f1(
i) - t_f0(
i)));
1741 t_delta(
i) /= edge_length;
1743 const double dot = t_delta(
i) * t_delta(
i);
1745 if (min_pair.first < 0 || min_pair.first > dot) {
1747 if (dot < tol_trim_close * tol_trim_close)
1748 min_pair = make_pair(dot, te);
1754 if (min_pair.first > -std::numeric_limits<double>::epsilon()) {
1755 add_edge(min_pair.second);
1763 if (!trim_cross_edges()) {
1765 const double dot = t_dist0(
i) * t_dist1(
i);
1766 const double dot_direction0 = t_dist0(
i) * t_edge_delta(
i);
1767 const double dot_direction1 = t_dist1(
i) * t_edge_delta(
i);
1769 if (dot < std::numeric_limits<double>::epsilon() &&
1770 dot_direction0 > -std::numeric_limits<double>::epsilon() &&
1771 dot_direction1 < std::numeric_limits<double>::epsilon()) {
1773 const double s0 = t_dist0(
i) * t_edge_delta(
i) / edge_length;
1774 const double s1 = t_dist1(
i) * t_edge_delta(
i) / edge_length;
1775 const double t_cut = s0 / (s0 - s1);
1783 CHKERR SaveData(moab)(
"edges_potentially_to_trim.vtk", cut_surface_edges);
1794 for (
auto t : adj_tets) {
1800 CHKERR moab.tag_get_data(
th, conn, num_nodes, &coords[0]);
1802 CHKERR moab.get_coords(conn, num_nodes, &coords[0]);
1804 for (
int n = 0;
n != 4; ++
n) {
1807 noalias(n_coords) = new_pos;
1812 m->second.rayPoint +
m->second.dIst *
m->second.unitRayDir;
1817 if (!std::isnormal(q)) {
1821 min_q = std::min(min_q, q);
1826 Range checked_verts;
1834 CHKERR moab.get_adjacencies(&
v, 1, 3,
false, adj_tets);
1836 double q = get_quality_change(adj_tets,
v, new_pos);
1839 double dist = norm_2(ray_dir);
1846 checked_verts.insert(
v);
1858 checked_verts.insert(
v);
1866 auto hi = verts_map.get<0>().upper_bound(tol_trim_close);
1867 verts_map.get<0>().erase(hi, verts_map.end());
1869 auto remove_verts = [&](
Range nodes) {
1870 for (
auto n : nodes) {
1871 auto r = verts_map.get<1>().equal_range(
n);
1872 verts_map.get<1>().erase(r.first, r.second);
1876 auto trim_verts = [&](
const Range verts,
const bool move) {
1877 VertMapMultiIndex verts_map_tmp;
1878 for (
auto p = corners.pair_begin(); p != corners.pair_end(); ++p) {
1879 auto lo = verts_map.get<1>().lower_bound(p->first);
1880 auto hi = verts_map.get<1>().upper_bound(p->second);
1881 verts_map_tmp.insert(lo, hi);
1884 for (
auto &
m : verts_map_tmp.get<0>())
1885 add_trim_vert(
m.v,
m.e);
1887 for (
auto &
m : verts_map_tmp.get<0>())
1888 add_no_move_trim(
m.v,
m.e);
1892 auto trim_edges = [&](
const Range ents,
const bool move) {
1893 VertMapMultiIndex verts_map_tmp;
1894 for (
auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
1895 auto lo = verts_map.get<2>().lower_bound(p->first);
1896 auto hi = verts_map.get<2>().upper_bound(p->second);
1897 verts_map_tmp.insert(lo, hi);
1898 verts_map.get<2>().erase(lo, hi);
1901 for (
auto &
m : verts_map_tmp.get<0>())
1902 add_trim_vert(
m.v,
m.e);
1904 for (
auto &
m : verts_map_tmp.get<0>())
1905 add_no_move_trim(
m.v,
m.e);
1909 auto intersect_self = [&](
Range &
a,
const Range b) {
a = intersect(
a, b); };
1911 map<std::string, Range> range_maps;
1916 intersect_self(range_maps[
"surface_skin"],
trimEdges);
1918 range_maps[
"fixed_edges_on_surface_skin"] =
1919 intersect(range_maps[
"surface_skin"], fix_edges);
1922 CHKERR moab.get_adjacencies(fixed_edges_verts, 1,
false,
1923 range_maps[
"fixed_edges_verts_edges"],
1924 moab::Interface::UNION);
1925 intersect_self(range_maps[
"fixed_edges_verts_edges"],
trimEdges);
1927 CHKERR moab.get_connectivity(
1928 range_maps[
"fixed_edges_verts_edges"],
1929 range_maps[
"fixed_edges_verts_edges_verts_on_the_skin"],
false);
1930 intersect_self(range_maps[
"fixed_edges_verts_edges_verts_on_the_skin"],
1934 trim_verts(corners,
false);
1935 remove_verts(corners);
1938 trim_edges(range_maps[
"fixed_edges_on_surface_skin"],
true);
1939 remove_verts(range_maps[
"fixed_edges_on_surface_skin_verts"]);
1942 trim_verts(range_maps[
"fixed_edges_verts_edges_verts_on_the_skin"],
false);
1943 remove_verts(range_maps[
"fixed_edges_verts_edges_verts_on_the_skin"]);
1946 trim_edges(range_maps[
"surface_skin"],
true);
1947 trim_verts(tets_skin_verts,
false);
1948 remove_verts(tets_skin_verts);
1950 for (
auto &
m : verts_map.get<0>())
1951 add_trim_vert(
m.v,
m.e);
1956 CHKERR moab.get_adjacencies(&
v, 1, 1,
false, adj);
1957 for (
auto e : adj) {
2034 Range *corner_nodes,
2038 moab::Interface &moab = m_field.
get_moab();
2039 Skinner skin(&moab);
2041 auto get_adj = [&moab](
const Range r,
const int dim) {
2044 CHKERR moab.get_adjacencies(r, dim,
false,
a, moab::Interface::UNION);
2046 CHKERR moab.get_connectivity(r,
a,
true);
2050 auto get_skin = [&skin](
const auto r) {
2052 CHKERR skin.find_skin(0, r,
false, s);
2059 auto trim_tets_skin_edges = get_adj(trim_tets_skin, 1);
2062 auto contarain_edges =
2065 contarain_edges.merge(
2066 intersect(fixed_edges->subset_by_type(MBEDGE), trim_surface_edges));
2071 barrier_vertices.merge(get_adj(
2072 intersect(get_adj(intersect(*corner_nodes, barrier_vertices), 2),
2077 auto get_nodes_with_one_node_on_fixed_edge_other_not = [&]() {
2078 const auto fixed_edges_on_surface =
2079 intersect(*fixed_edges, trim_surface_edges);
2080 const auto skin_fixed_edges_on_surface =
get_skin(fixed_edges_on_surface);
2081 const auto barrier_nodes = subtract(skin_fixed_edges_on_surface,
2083 return barrier_nodes;
2087 barrier_vertices.merge(get_nodes_with_one_node_on_fixed_edge_other_not());
2089 auto add_close_surface_barrier = [&]() {
2101 test_edges = subtract(test_edges, *fixed_edges);
2102 auto trim_surface_nodes = get_adj(test_edges, 0);
2103 trim_surface_nodes = subtract(trim_surface_nodes, barrier_vertices);
2105 trim_surface_nodes =
2106 subtract(trim_surface_nodes, get_adj(*fixed_edges, 0));
2109 trim_skin.merge(contarain_edges);
2113 trim_skin.merge(
fRont);
2115 trim_skin.merge(intersect(*fixed_edges, trim_surface_edges));
2117 if (
debug && !trim_skin.empty())
2122 CHKERR moab.tag_get_data(
th, trim_surface_nodes, &*coords.begin());
2124 CHKERR moab.get_coords(trim_surface_nodes, &*coords.begin());
2126 if (!trim_skin.empty()) {
2128 std::vector<double> min_distances(trim_surface_nodes.size(), -1);
2130 &*coords.begin(), trim_surface_nodes.size(), trim_skin,
2131 &*min_distances.begin());
2133 auto coords_ptr = &*coords.begin();
2134 auto min_dist = &*min_distances.begin();
2136 std::vector<EntityHandle> add_nodes;
2137 add_nodes.reserve(trim_surface_nodes.size());
2139 for (
auto n : trim_surface_nodes) {
2141 if ((*min_dist) > std::numeric_limits<double>::epsilon()) {
2146 &point_out[0], facets_out);
2153 normal /= norm_2(normal);
2156 double dist = norm_2(
delta);
2157 if (dist <
tol * (*min_dist))
2158 add_nodes.emplace_back(
n);
2165 barrier_vertices.insert_list(add_nodes.begin(), add_nodes.end());
2171 auto remove_faces_on_skin = [&]() {
2174 if (!skin_faces.empty()) {
2175 barrier_vertices.merge(get_adj(skin_faces, 0));
2176 for (
auto f : skin_faces)
2182 auto get_trim_free_edges = [&]() {
2184 Range trim_surf_skin;
2186 trim_surf_skin = subtract(trim_surf_skin, trim_tets_skin_edges);
2188 Range trim_surf_skin_verts;
2189 CHKERR moab.get_connectivity(trim_surf_skin, trim_surf_skin_verts,
true);
2190 for (
auto e : barrier_vertices)
2191 trim_surf_skin_verts.erase(e);
2194 CHKERR moab.get_adjacencies(trim_surf_skin_verts, 1,
false, free_edges,
2195 moab::Interface::UNION);
2197 subtract(intersect(free_edges, trim_surf_skin), contarain_edges);
2202 CHKERR remove_faces_on_skin();
2203 CHKERR add_close_surface_barrier();
2205 if (
debug && !barrier_vertices.empty())
2211 while (!(out_edges = get_trim_free_edges()).empty()) {
2215 "trimNewSurfaces_" + boost::lexical_cast<std::string>(nn) +
".vtk",
2218 if (
debug && !out_edges.empty())
2220 "trimNewSurfacesOutsideVerts_" +
2221 boost::lexical_cast<std::string>(nn) +
".vtk",
2224 Range outside_faces;
2225 CHKERR moab.get_adjacencies(out_edges, 2,
false, outside_faces,
2226 moab::Interface::UNION);
2233 "trimNewSurfaces_" + boost::lexical_cast<std::string>(nn) +
".vtk",
2309 const Range &fixed_edges,
const Range &corner_nodes,
Range &edges_to_merge,
2313 moab::Interface &moab = m_field.
get_moab();
2321 const bool onlyIfImproveQuality;
2325 MergeNodes(
CoreInterface &m_field,
const bool only_if_improve_quality,
2326 Tag th,
bool update_mehsets)
2327 : mField(m_field), onlyIfImproveQuality(only_if_improve_quality),
2328 tH(
th), updateMehsets(update_mehsets) {
2334 bool add_child =
true) {
2335 moab::Interface &moab = mField.
get_moab();
2339 CHKERR moab.get_adjacencies(conn, 2, 3,
false, vert_tets,
2340 moab::Interface::UNION);
2341 vert_tets = intersect(vert_tets, proc_tets);
2344 onlyIfImproveQuality, 0, line_search,
2349 Range::iterator lo, hi = proc_tets.begin();
2350 for (
auto pt = vert_tets.pair_begin(); pt != vert_tets.pair_end();
2352 lo = proc_tets.lower_bound(hi, proc_tets.end(), pt->first);
2353 if (lo != proc_tets.end()) {
2354 hi = proc_tets.upper_bound(lo, proc_tets.end(), pt->second);
2355 proc_tets.erase(lo, hi);
2359 proc_tets.merge(out_tets);
2363 struct ChangeChild {
2365 ChangeChild(
const EntityHandle child) : child(child) {}
2371 std::vector<
decltype(parentsChildMap.get<0>().begin())> it_vec;
2372 it_vec.reserve(parentsChildMap.size());
2374 for (
auto &p : parent_child_map) {
2377 for (
auto it = parentsChildMap.get<0>().equal_range(p.pArent);
2378 it.first != it.second; ++it.first)
2379 it_vec.emplace_back(it.first);
2381 for (
auto it = parentsChildMap.get<1>().equal_range(p.pArent);
2382 it.first != it.second; ++it.first)
2383 it_vec.emplace_back(parentsChildMap.project<0>(it.first));
2385 for (
auto &it : it_vec)
2386 parentsChildMap.modify(it, ChangeChild(p.cHild));
2389 parentsChildMap.insert(parent_child_map.begin(),
2390 parent_child_map.end());
2396 Range ¬_merged_edges,
2398 moab::Interface &moab = mField.
get_moab();
2402 std::vector<EntityHandle> parents_ents_vec(parentsChildMap.size());
2403 for (
auto &it : parentsChildMap)
2404 parents_ents_vec.emplace_back(it.pArent);
2406 parent_ents.insert_list(parents_ents_vec.begin(),
2407 parents_ents_vec.end());
2409 Range surf_parent_ents = intersect(new_surf, parent_ents);
2410 new_surf = subtract(new_surf, surf_parent_ents);
2411 Range child_surf_ents;
2412 CHKERR updateRangeByChilds(parentsChildMap, surf_parent_ents,
2414 new_surf.merge(child_surf_ents);
2416 Range edges_to_merge_parent_ents =
2417 intersect(edges_to_merge, parent_ents);
2418 edges_to_merge = subtract(edges_to_merge, edges_to_merge_parent_ents);
2419 Range merged_child_edge_ents;
2420 CHKERR updateRangeByChilds(parentsChildMap, edges_to_merge_parent_ents,
2421 merged_child_edge_ents);
2423 Range not_merged_edges_child_ents =
2424 intersect(not_merged_edges, parent_ents);
2426 subtract(not_merged_edges, not_merged_edges_child_ents);
2427 Range not_merged_child_edge_ents;
2428 CHKERR updateRangeByChilds(parentsChildMap, not_merged_edges_child_ents,
2429 not_merged_child_edge_ents);
2431 merged_child_edge_ents =
2432 subtract(merged_child_edge_ents, not_merged_child_edge_ents);
2433 edges_to_merge.merge(merged_child_edge_ents);
2434 not_merged_edges.merge(not_merged_child_edge_ents);
2436 if (updateMehsets) {
2441 CHKERR moab.get_entities_by_handle(cubit_meshset, meshset_ents,
2444 CHKERR updateRangeByChilds(parentsChildMap, meshset_ents,
2446 CHKERR moab.add_entities(cubit_meshset, child_ents);
2456 std::vector<EntityHandle> childsVec;
2463 childsVec.reserve(parents.size());
2464 for (
auto pit = parents.pair_begin(); pit != parents.pair_end(); pit++) {
2465 auto it = parent_child_map.lower_bound(pit->first);
2466 if (it != parent_child_map.end()) {
2467 for (
auto hi_it = parent_child_map.upper_bound(pit->second);
2469 childsVec.emplace_back(it->cHild);
2472 childs.insert_list(childsVec.begin(), childsVec.end());
2483 moab::Interface &moab;
2484 const double maxLength;
2486 : tH(
th), mField(m_field), moab(m_field.
get_moab()),
2487 maxLength(max_length) {
2490 acceptedThrasholdMergeQuality = 0.5;
2497 double acceptedThrasholdMergeQuality;
2502 double &ave)
const {
2505 std::array<double, 12> coords;
2507 VectorAdaptor s0(3, ublas::shallow_array_adaptor<double>(3, &coords[0]));
2508 VectorAdaptor s1(3, ublas::shallow_array_adaptor<double>(3, &coords[3]));
2511 struct NodeQuality {
2514 NodeQuality(
const EntityHandle node) : node(node), quality(1) {}
2517 typedef multi_index_container<
2518 NodeQuality, indexed_by<
2522 hashed_non_unique<tag<Ent_mi_tag>,
2524 &NodeQuality::node>>
2527 NodeQuality_sequence;
2529 NodeQuality_sequence node_quality_sequence;
2532 CHKERR moab.get_connectivity(tets, edges_nodes,
false);
2534 CHKERR moab.get_adjacencies(edges, 3,
false, edges_tets,
2535 moab::Interface::UNION);
2536 edges_tets = intersect(edges_tets, tets);
2538 for (
auto node : edges_nodes)
2539 node_quality_sequence.emplace_back(node);
2541 for (
auto tet : edges_tets) {
2543 CHKERR moab.get_connectivity(tet, conn, num_nodes,
true);
2545 CHKERR moab.tag_get_data(tH, conn, num_nodes, coords.data());
2547 CHKERR moab.get_coords(conn, num_nodes, coords.data());
2549 const double q = Tools::volumeLengthQuality(coords.data());
2551 for (
auto n : {0, 1, 2, 3}) {
2552 auto it = node_quality_sequence.get<1>().find(conn[
n]);
2553 if (it != node_quality_sequence.get<1>().end())
2554 const_cast<double &
>(it->quality) = std::min(q, it->quality);
2558 for (
auto edge : edges) {
2560 CHKERR moab.get_connectivity(edge, conn, num_nodes,
true);
2563 CHKERR moab.tag_get_data(tH, conn, num_nodes, coords.data());
2565 CHKERR moab.get_coords(conn, num_nodes, coords.data());
2568 for (
auto n : {0, 1}) {
2569 auto it = node_quality_sequence.get<1>().find(conn[
n]);
2570 if (it != node_quality_sequence.get<1>().end())
2571 q = std::min(q, it->quality);
2574 if (q < acceptedThrasholdMergeQuality) {
2575 noalias(
delta) = (s0 - s1) / maxLength;
2577 double val = pow(q, gammaQ) * pow(dot, 0.5 * gammaL);
2583 for (LengthMapData_multi_index::nth_index<0>::type::iterator mit =
2584 length_map.get<0>().begin();
2585 mit != length_map.get<0>().end(); mit++) {
2586 ave += mit->qUality;
2588 ave /= length_map.size();
2606 SURFACE_SKIN = 1 << 2,
2607 FRONT_ENDS = 1 << 3,
2609 FIX_CORNERS = 1 << 5
2612 typedef map<int, Range> SetsMap;
2615 const Range &fixed_edges,
2616 const Range &corner_nodes,
2617 const Range &constrain_surface,
2618 SetsMap &sets_map)
const {
2619 moab::Interface &moab(mField.
get_moab());
2620 Skinner skin(&moab);
2623 sets_map[FIX_CORNERS].merge(corner_nodes);
2625 CHKERR moab.get_connectivity(fixed_edges, fixed_verts,
true);
2626 sets_map[FIX_EDGES].swap(fixed_verts);
2629 CHKERR skin.find_skin(0, tets,
false, tets_skin);
2630 Range tets_skin_edges;
2631 CHKERR moab.get_adjacencies(tets_skin, 1,
false, tets_skin_edges,
2632 moab::Interface::UNION);
2635 Range constrain_surface_verts;
2636 CHKERR moab.get_connectivity(constrain_surface, constrain_surface_verts,
2638 Range constrain_surface_edges;
2639 CHKERR moab.get_adjacencies(constrain_surface, 1,
false,
2640 constrain_surface_edges,
2641 moab::Interface::UNION);
2646 Range front_in_the_body;
2647 front_in_the_body = subtract(surface_skin, tets_skin_edges);
2648 Range front_in_the_body_verts;
2649 CHKERR moab.get_connectivity(front_in_the_body, front_in_the_body_verts,
2652 CHKERR skin.find_skin(0, front_in_the_body,
false, front_ends);
2654 intersect(front_in_the_body_verts, constrain_surface_verts));
2655 sets_map[FRONT_ENDS].swap(front_ends);
2657 Range surface_skin_verts;
2658 CHKERR moab.get_connectivity(surface_skin, surface_skin_verts,
true);
2659 sets_map[SURFACE_SKIN].swap(surface_skin_verts);
2662 Range surface_verts;
2664 sets_map[SURFACE_SKIN].merge(
2665 intersect(constrain_surface_verts, surface_verts));
2666 sets_map[SURFACE].swap(surface_verts);
2669 Range tets_skin_verts;
2670 CHKERR moab.get_connectivity(tets_skin, tets_skin_verts,
true);
2671 sets_map[SKIN].swap(tets_skin_verts);
2672 sets_map[SKIN].merge(constrain_surface_verts);
2675 CHKERR moab.get_connectivity(tets, tets_verts,
true);
2676 sets_map[FREE].swap(tets_verts);
2682 Range &proc_tets)
const {
2683 moab::Interface &moab(mField.
get_moab());
2685 Range edges_to_merge_verts;
2686 CHKERR moab.get_connectivity(edges_to_merge, edges_to_merge_verts,
true);
2687 Range edges_to_merge_verts_tets;
2688 CHKERR moab.get_adjacencies(edges_to_merge_verts, 3,
false,
2689 edges_to_merge_verts_tets,
2690 moab::Interface::UNION);
2691 edges_to_merge_verts_tets = intersect(edges_to_merge_verts_tets, tets);
2692 proc_tets.swap(edges_to_merge_verts_tets);
2697 const Range &fixed_edges,
2698 const Range &corner_nodes,
2699 const Range &constrain_surface,
2700 Range &edges_to_merge,
2701 Range ¬_merged_edges) {
2702 moab::Interface &moab(mField.
get_moab());
2706 Skinner skin(&moab);
2708 CHKERR skin.find_skin(0, tets,
false, tets_skin);
2713 Range constrain_surface_verts;
2714 CHKERR moab.get_connectivity(constrain_surface, constrain_surface_verts,
2716 Range constrain_surface_edges;
2717 CHKERR moab.get_adjacencies(constrain_surface, 1,
false,
2718 constrain_surface_edges,
2719 moab::Interface::UNION);
2722 Range tets_skin_edges;
2723 CHKERR moab.get_adjacencies(tets_skin, 1,
false, tets_skin_edges,
2724 moab::Interface::UNION);
2726 Range surface_front;
2727 surface_front = subtract(surface_skin, tets_skin_edges);
2728 Range surface_front_nodes;
2729 CHKERR moab.get_connectivity(surface_front, surface_front_nodes,
true);
2732 CHKERR skin.find_skin(0, surface_front,
false, ends_nodes);
2733 ends_nodes.merge(intersect(surface_front_nodes, constrain_surface_verts));
2736 surface_skin.merge(constrain_surface);
2737 tets_skin_edges.merge(constrain_surface_edges);
2740 Range surface_edges;
2741 CHKERR moab.get_adjacencies(
surface, 1,
false, surface_edges,
2742 moab::Interface::UNION);
2744 Range surface_edges_verts;
2745 CHKERR moab.get_connectivity(surface_edges, surface_edges_verts,
true);
2747 Range tets_skin_edges_verts;
2748 CHKERR moab.get_connectivity(tets_skin_edges, tets_skin_edges_verts,
2751 Range edges_to_remove;
2755 Range ents_nodes_and_edges;
2756 ents_nodes_and_edges.merge(tets_skin_edges_verts);
2757 ents_nodes_and_edges.merge(tets_skin_edges);
2758 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2761 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2762 not_merged_edges.merge(edges_to_remove);
2766 Range ents_nodes_and_edges;
2767 ents_nodes_and_edges.merge(surface_edges_verts);
2768 ents_nodes_and_edges.merge(surface_edges);
2769 ents_nodes_and_edges.merge(tets_skin_edges_verts);
2770 ents_nodes_and_edges.merge(tets_skin_edges);
2771 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2774 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2775 not_merged_edges.merge(edges_to_remove);
2778 Range fixed_edges_nodes;
2779 CHKERR moab.get_connectivity(fixed_edges, fixed_edges_nodes,
true);
2781 Range ents_nodes_and_edges;
2782 ents_nodes_and_edges.merge(fixed_edges_nodes);
2783 ents_nodes_and_edges.merge(ends_nodes);
2784 ents_nodes_and_edges.merge(corner_nodes);
2785 ents_nodes_and_edges.merge(fixed_edges);
2786 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2789 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2790 not_merged_edges.merge(edges_to_remove);
2793 CHKERR removeSelfConectingEdges(surface_edges, edges_to_remove,
false);
2794 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2795 not_merged_edges.merge(edges_to_remove);
2799 Range ents_nodes_and_edges;
2800 ents_nodes_and_edges.merge(surface_skin);
2801 ents_nodes_and_edges.merge(fixed_edges_nodes);
2802 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2805 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2806 not_merged_edges.merge(edges_to_remove);
2810 Range ents_nodes_and_edges;
2811 ents_nodes_and_edges.merge(surface_skin.subset_by_type(MBEDGE));
2812 ents_nodes_and_edges.merge(fixed_edges.subset_by_type(MBEDGE));
2813 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2816 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2817 not_merged_edges.merge(edges_to_remove);
2821 Range ents_nodes_and_edges;
2822 ents_nodes_and_edges.merge(surface_front_nodes);
2823 ents_nodes_and_edges.merge(surface_front);
2824 ents_nodes_and_edges.merge(tets_skin_edges_verts);
2825 ents_nodes_and_edges.merge(tets_skin_edges);
2826 CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2829 edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2830 not_merged_edges.merge(edges_to_remove);
2837 Range &edges_to_remove,
2839 moab::Interface &moab(mField.
get_moab());
2842 Range ents_nodes = ents.subset_by_type(MBVERTEX);
2843 if (ents_nodes.empty()) {
2844 CHKERR moab.get_connectivity(ents, ents_nodes,
true);
2847 Range ents_nodes_edges;
2848 CHKERR moab.get_adjacencies(ents_nodes, 1,
false, ents_nodes_edges,
2849 moab::Interface::UNION);
2851 Range ents_nodes_edges_nodes;
2852 CHKERR moab.get_connectivity(ents_nodes_edges, ents_nodes_edges_nodes,
2855 ents_nodes_edges_nodes = subtract(ents_nodes_edges_nodes, ents_nodes);
2856 Range ents_nodes_edges_nodes_edges;
2857 CHKERR moab.get_adjacencies(ents_nodes_edges_nodes, 1,
false,
2858 ents_nodes_edges_nodes_edges,
2859 moab::Interface::UNION);
2862 subtract(ents_nodes_edges, ents_nodes_edges_nodes_edges);
2864 subtract(ents_nodes_edges, ents.subset_by_type(MBEDGE));
2866 edges_to_remove.swap(ents_nodes_edges);
2874 Range not_merged_edges;
2876 .removeBadEdges(
surface, tets, fixed_edges, corner_nodes,
2878 Toplogy::SetsMap sets_map;
2883 for (Toplogy::SetsMap::reverse_iterator sit = sets_map.rbegin();
2884 sit != sets_map.rend(); sit++) {
2885 std::string name =
"classification_verts_" +
2886 boost::lexical_cast<std::string>(sit->first) +
".vtk";
2887 if (!sit->second.empty())
2892 CHKERR Toplogy(m_field,
th).getProcTets(tets, edges_to_merge, proc_tets);
2893 out_tets = subtract(tets, proc_tets);
2896 Range all_out_ents = out_tets;
2897 for (
int dd = 2; dd >= 0; dd--) {
2898 CHKERR moab.get_adjacencies(out_tets, dd,
false, all_out_ents,
2899 moab::Interface::UNION);
2905 int nb_nodes_merged = 0;
2909 auto save_merge_step = [&](
const int pp,
const Range collapsed_edges) {
2912 CHKERR moab.get_adjacencies(proc_tets, 2,
false, adj_faces,
2913 moab::Interface::UNION);
2915 name =
"node_merge_step_" + boost::lexical_cast<std::string>(pp) +
".vtk";
2917 name, unite(intersect(new_surf, adj_faces), collapsed_edges));
2919 "edges_to_merge_step_" + boost::lexical_cast<std::string>(pp) +
".vtk";
2921 name, unite(intersect(new_surf, adj_faces), edges_to_merge));
2928 double ave0 = 0, ave = 0, min = 0, min_p = 0, min_pp;
2931 int nb_nodes_merged_p = nb_nodes_merged;
2938 if(!length_map.empty())
2939 min = length_map.get<2>().begin()->qUality;
2945 Range collapsed_edges;
2946 MergeNodes merge_nodes(m_field,
true,
th, update_meshsets);
2948 for (
auto mit = length_map.get<0>().begin();
2949 mit != length_map.get<0>().end(); mit++, nn++) {
2953 auto get_father_and_mother =
2958 CHKERR moab.get_connectivity(mit->eDge, conn, num_nodes,
true);
2959 std::array<int, 2> conn_type = {0, 0};
2960 for (
int nn = 0; nn != 2; nn++) {
2961 for (Toplogy::SetsMap::reverse_iterator sit = sets_map.rbegin();
2962 sit != sets_map.rend(); sit++) {
2963 if (sit->second.find(conn[nn]) != sit->second.end()) {
2964 conn_type[nn] |= sit->first;
2968 int type_father, type_mother;
2969 if (conn_type[0] > conn_type[1]) {
2972 type_father = conn_type[0];
2973 type_mother = conn_type[1];
2977 type_father = conn_type[1];
2978 type_mother = conn_type[0];
2980 if (type_father == type_mother) {
2986 int line_search = 0;
2988 CHKERR get_father_and_mother(father, mother, line_search);
2989 CHKERR merge_nodes.mergeNodes(line_search, father, mother, proc_tets);
2991 const EntityHandle father_and_mother[] = {father, mother};
2993 CHKERR moab.get_adjacencies(father_and_mother, 1, 3,
false, adj_tets);
2994 Range adj_tets_nodes;
2995 CHKERR moab.get_connectivity(adj_tets, adj_tets_nodes,
true);
2997 CHKERR moab.get_adjacencies(adj_tets_nodes, 1,
false, adj_edges,
2998 moab::Interface::UNION);
2999 for (
auto ait : adj_edges) {
3000 auto miit = length_map.get<1>().find(ait);
3001 if (miit != length_map.get<1>().end())
3005 collapsed_edges.insert(mit->eDge);
3008 if (nn >
static_cast<int>(length_map.size() / fraction_level))
3010 if (mit->qUality > ave)
3015 CHKERR merge_nodes.updateRangeByChilds(new_surf, edges_to_merge,
3016 not_merged_edges,
true);
3019 "(%d) Number of nodes merged %d ave q %3.4e min q %3.4e", pp,
3020 nb_nodes_merged, ave, min);
3023 CHKERR save_merge_step(pp + 1, collapsed_edges);
3025 if (nb_nodes_merged == nb_nodes_merged_p)
3027 if (min > 1e-2 && min == min_pp)
3033 CHKERR moab.get_adjacencies(proc_tets, 1,
false, adj_edges,
3034 moab::Interface::UNION);
3035 edges_to_merge = intersect(edges_to_merge, adj_edges);
3037 .removeBadEdges(new_surf, proc_tets, fixed_edges, corner_nodes,
3041 auto reconstruct_refined_ents = [&]() {
3052 CHKERR reconstruct_refined_ents();
3058 out_tets.merge(proc_tets);
3060 CHKERR moab.get_adjacencies(out_tets, 2,
false, adj_faces,
3061 moab::Interface::UNION);
3062 new_surf = intersect(new_surf, adj_faces);