| Base 5112d2 | Head #4506 f0a4b5 | ||||
|---|---|---|---|---|---|
| Total | Total | +/- | New | ||
| Rate | 65.72% | 65.74% | +0.01% | 100.00% | |
| Hits | 78898 | 78962 | +64 | 71 | |
| Misses | 41151 | 41158 | +7 | 0 | |
| Filename | Stmts | Miss | Cover |
|---|---|---|---|
| src/mesh/mesh_netgen_interface.C | +59 | +2 | +1.09% |
| src/mesh/mesh_tet_interface.C | +12 | +4 | -0.25% |
| src/mesh/mesh_triangle_holes.C | 0 | +1 | -0.27% |
| TOTAL | +71 | +7 | +0.01% |
codecodecode+
89 90 91 92 + 93 + 94 + 95 + 96 97 98 |
LOG_SCOPE("triangulate()", "NetGenMeshInterface"); if (_elem_type != TET4 && _elem_type != TET10 && _elem_type != TET14) libmesh_not_implemented(); // We're hoping to do volume_to_surface_mesh in parallel at least, // but then we'll need to serialize any hole meshes to rank 0 so it |
102 103 104 105 + 106 107 108 109 110 111 + 112 113 114 + 115 116 + 117 + 118 119 + 120 + 121 122 + 123 124 + 125 + 126 + 127 + 128 + 129 130 131 + 132 133 134 + 135 + 136 + 137 138 + 139 + 140 + 141 + 142 143 144 145 146 + 147 + 148 149 150 |
// quadratic boundary elements before stripping them to TRI3 for // NetGen. We key by sorted position pairs (not node IDs) so that // outer mesh and hole mesh node namespaces cannot conflict. std::map<std::pair<Point,Point>, Point> edge_midpoints; // TRI7 boundary faces additionally carry a face-centroid node (local index // 6) that TET14 output reproduces (its faces are TRI7). Record those too, // keyed by the sorted triple of the face's three corner positions so the // key is independent of node id and rotation. std::map<std::array<Point,3>, Point> face_centroids; auto record_and_strip = [&edge_midpoints, &face_centroids](UnstructuredMesh & m) { bool has_quadratic = false; for (const auto & elem : m.element_ptr_range()) { if (elem->type() != TRI6 && elem->type() != TRI7) continue; has_quadratic = true; // TRI6/TRI7: edge e runs node[e]→node[(e+1)%3], midpoint=node[e+3] for (auto e : make_range(3u)) { const Point & pa = elem->point(e); const Point & pb = elem->point((e+1)%3); auto key = pa < pb ? std::make_pair(pa,pb) : std::make_pair(pb,pa); edge_midpoints[key] = elem->point(e+3); } // TRI7: node 6 is the face-centroid node. if (elem->type() == TRI7) { std::array<Point,3> corners = {elem->point(0), elem->point(1), elem->point(2)}; std::sort(corners.begin(), corners.end()); face_centroids[corners] = elem->point(6); } } if (has_quadratic) m.all_first_order(); }; const BoundingBox mesh_bb = MeshTetInterface::volume_to_surface_mesh(this->_mesh); if (_elem_type != TET4) record_and_strip(this->_mesh); std::vector<MeshSerializer> hole_serializers; if (_holes) |
153 154 155 156 + 157 + 158 159 160 |
const BoundingBox hole_bb = MeshTetInterface::volume_to_surface_mesh(*hole); if (_elem_type != TET4) record_and_strip(*hole); libmesh_error_msg_if (!mesh_bb.contains(hole_bb), |
177 178 179 180 + 181 182 + 183 + 184 185 186 |
// the mesh was serialized on every rank, so it is identical everywhere and // this post-broadcast fixup is deterministic. auto increase_order_and_restore_midpoints = [this, &edge_midpoints, &face_centroids]() { if (_elem_type == TET4) return; // NetGen (and volume_to_surface_mesh) can leave gaps in rank 0's // element and node id spaces, while broadcast() compacts them on the |
190 191 192 193 + 194 195 196 197 + 198 199 200 |
// renumber_nodes_and_elements() itself performs a collective reduction // for the unique-id counter, so it must be called on all ranks together, // never on rank 0 alone (that would deadlock the others in broadcast()). this->_mesh.renumber_nodes_and_elements(); // find_neighbors() is needed before all_second_order() can place // shared edge midpoints correctly. this->_mesh.find_neighbors(); // Refresh the cached element dimensions. We just replaced the 2D // TRI3 surface elements with 3D TET4 volume elements, but the mesh's |
205 206 207 208 + 209 210 + 211 212 213 214 + 215 + 216 + 217 218 + 219 220 221 222 223 + 224 + 225 226 + 227 + 228 + 229 + 230 + 231 + 232 + 233 234 235 236 237 + 238 239 240 + 241 + 242 + 243 + 244 + 245 246 + 247 + 248 249 250 |
// nodes of a TET10, so adjacent elements' unique_id ranges overlap and // collide. cache_elem_data() recomputes the dimension to 3 (reserving // 27-8=19 slots) before the order increase runs. this->_mesh.cache_elem_data(); this->increase_tet_order(); // Move auto-placed geometric midpoints to the recorded positions, // preserving any curvature from the original quadratic boundary. if (!edge_midpoints.empty() || !face_centroids.empty()) for (Elem * elem : _mesh.element_ptr_range()) for (auto s : elem->side_index_range()) { if (elem->neighbor_ptr(s)) continue; // build_side_ptr() returns a TRI6 (TET10) or TRI7 (TET14) // whose node pointers reference the actual mesh nodes; point() // assignments update mesh node coordinates in place. auto side = elem->build_side_ptr(s); for (auto e : make_range(3u)) { const Point & pa = side->point(e); const Point & pb = side->point((e+1)%3); auto key = pa < pb ? std::make_pair(pa,pb) : std::make_pair(pb,pa); if (auto it = edge_midpoints.find(key); it != edge_midpoints.end()) side->point(e+3) = it->second; } // TRI7 faces (TET14 output) also carry a face-centroid node // at local index 6; restore its recorded curved position. if (side->type() == TRI7) { std::array<Point,3> corners = {side->point(0), side->point(1), side->point(2)}; std::sort(corners.begin(), corners.end()); if (auto it = face_centroids.find(corners); it != face_centroids.end()) side->point(6) = it->second; } } }; // This should probably only be done on rank 0, but the API is // designed with the hope that we'll parallelize it eventually |
271 272 273 274 + 275 276 277 |
"NetGen failed to generate any tetrahedra"); // Increase the element order collectively, in lockstep with rank 0. increase_order_and_restore_midpoints(); this->_mesh.prepare_for_use(); return; |
575 576 577 578 + 579 580 581 |
// collective communication, so it must not run on rank 0 alone -- doing so // would deadlock against the other ranks waiting in broadcast() above. MeshCommunication().broadcast(this->_mesh); increase_order_and_restore_midpoints(); this->_mesh.prepare_for_use(); } |
700 701 702 703 + 704 705 + 706 707 + 708 + 709 + 710 + 711 + 712 + 713 + 714 + 715 + 716 + 717 718 719 |
void MeshTetInterface::increase_tet_order() { switch (_elem_type) { case TET4: return; case TET10: _mesh.all_second_order(); break; case TET14: _mesh.all_complete_order(); break; default: libmesh_not_implemented(); } } |
270 271 272 273 274 275 276 |
{ ray_target = inside - Point(1); intersection_distances = this->find_ray_intersections(inside, ray_target); } // I'd make this an assert, but I'm not 100% confident we can't |