PolyFEM
Loading...
Searching...
No Matches
NCMesh3D.cpp
Go to the documentation of this file.
4
6
7#include <igl/writeMESH.h>
8
9#include <geogram/mesh/mesh_io.h>
10#include <fstream>
11
12using namespace polyfem::utils;
13
14namespace polyfem
15{
16 namespace mesh
17 {
18 void NCMesh3D::remove_elements(const std::vector<bool> &keep)
19 {
20 assert(keep.size() == n_cells());
21
22 std::vector<int> old_node_ids(vertices.size(), -1);
23 if (has_node_ids())
24 for (int v = 0; v < n_vertices(); ++v)
25 old_node_ids[valid_to_all_vertex(v)] = node_ids_[v];
26 std::vector<int> old_boundary_ids(faces.size(), -1);
27 if (has_boundary_ids())
28 for (int f = 0; f < n_faces(); ++f)
29 old_boundary_ids[valid_to_all_face(f)] = boundary_ids_[f];
30
31 for (int e = 0; e < keep.size(); ++e)
32 {
33 if (keep[e])
34 continue;
35 const int full_id = valid_to_all_elem(e);
36 auto &element = elements[full_id];
37 element.is_ghost = true;
38 for (const int face : element.faces)
39 faces[face].remove_element(full_id);
40 for (const int edge : element.edges)
41 edges[edge].remove_element(full_id);
42 for (const int vertex : element.vertices)
43 vertices[vertex].remove_element(full_id);
44 --n_elements;
45 }
48
49 if (has_node_ids())
50 {
51 node_ids_.resize(n_vertices());
52 for (int v = 0; v < n_vertices(); ++v)
53 node_ids_[v] = old_node_ids[valid_to_all_vertex(v)];
54 }
55 if (has_boundary_ids())
56 {
57 boundary_ids_.resize(n_faces());
58 for (int f = 0; f < n_faces(); ++f)
59 {
60 const int old_id = old_boundary_ids[valid_to_all_face(f)];
61 boundary_ids_[f] = old_id < 0 ? get_default_boundary_id(f) : old_id;
62 faces[valid_to_all_face(f)].boundary_id = boundary_ids_[f];
63 }
64 }
65 }
66
67 int NCMesh3D::face_edge(const int f_id, const int le_id) const
68 {
69 const int v0 = faces[valid_to_all_face(f_id)].vertices(le_id);
70 const int v1 = faces[valid_to_all_face(f_id)].vertices((le_id + 1) % 3);
71 const int e_id = find_edge(v0, v1);
72 return all_to_valid_edge(e_id);
73 }
74
75 void NCMesh3D::refine(const int n_refinement, const double t)
76 {
77 if (n_refinement <= 0)
78 return;
80 std::vector<bool> refine_mask(elements.size(), false);
81 for (int i = 0; i < elements.size(); i++)
82 if (elements[i].is_valid())
83 refine_mask[i] = true;
84
85 for (int i = 0; i < refine_mask.size(); i++)
86 if (refine_mask[i])
88
89 refine(n_refinement - 1, t);
90 }
91
92 bool NCMesh3D::is_boundary_element(const int element_global_id) const
93 {
94 assert(index_prepared);
95 for (int lv = 0; lv < n_cell_edges(element_global_id); lv++)
96 if (is_boundary_vertex(cell_vertex(element_global_id, lv)))
97 return true;
98
99 return false;
100 }
101
103 {
104 if (data.has_polyhedral_topology())
105 return false;
106 const Eigen::MatrixXd &V = data.vertices;
107 const Eigen::MatrixXi &F = data.elements;
108 if (F.cols() != 4 || F.minCoeff() < 0)
109 return false;
110 n_elements = 0;
111 elements.clear();
112 vertices.clear();
113 edges.clear();
114 midpointMap.clear();
115 edgeMap.clear();
116 faceMap.clear();
117 refineHistory.clear();
118 index_prepared = false;
119 adj_prepared = false;
120
121 vertices.reserve(V.rows());
122 for (int i = 0; i < V.rows(); i++)
123 {
124 vertices.emplace_back(V.row(i));
125 }
126 for (int i = 0; i < F.rows(); i++)
127 {
128 add_element(F.row(i), -1);
129 }
130
131 prepare_mesh();
132
133 return true;
134 }
135
136 void NCMesh3D::attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector<std::vector<int>> &nodes)
137 {
138 for (int f = 0; f < n_cells(); ++f)
139 if (nodes[f].size() != 4)
140 throw std::runtime_error("NCMesh doesn't support high order mesh!");
141 }
142
144 {
145 polyfem::RowVectorNd min, max;
146 bounding_box(min, max);
147
148 auto extent = max - min;
149 double scale = extent.maxCoeff();
150
151 for (auto &v : vertices)
152 v.pos = (v.pos - min.transpose()) / scale;
153 }
154
163 double NCMesh3D::edge_length(const int gid) const
164 {
165 const int v1 = edge_vertex(gid, 0);
166 const int v2 = edge_vertex(gid, 1);
167
168 return (point(v1) - point(v2)).norm();
169 }
170
171 RowVectorNd NCMesh3D::point(const int global_index) const
172 {
173 return vertices[valid_to_all_vertex(global_index)].pos.transpose();
174 }
175
176 void NCMesh3D::set_point(const int global_index, const RowVectorNd &p)
177 {
178 vertices[valid_to_all_vertex(global_index)].pos = p;
179 }
180
182 {
183 const int v1 = edge_vertex(e, 0);
184 const int v2 = edge_vertex(e, 1);
185
186 return 0.5 * (point(v1) + point(v2));
187 }
189 {
190 const int v1 = face_vertex(f, 0);
191 const int v2 = face_vertex(f, 1);
192 const int v3 = face_vertex(f, 2);
193
194 return (point(v1) + point(v2) + point(v3)) / 3.;
195 }
197 {
198 const int v1 = face_vertex(c, 0);
199 const int v2 = face_vertex(c, 1);
200 const int v3 = face_vertex(c, 2);
201
202 return (point(v1) + point(v2) + point(v3)) / 3.;
203 }
204
206 {
207 min = vertices[0].pos;
208 max = vertices[0].pos;
209
210 for (const auto &v : vertices)
211 {
212 for (int d = 0; d < 3; d++)
213 {
214 if (v.pos[d] > max[d])
215 max[d] = v.pos[d];
216 if (v.pos[d] < min[d])
217 min[d] = v.pos[d];
218 }
219 }
220 }
221
222 void NCMesh3D::compute_boundary_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &, bool)> &marker)
223 {
224 boundary_ids_.resize(n_faces());
225 std::fill(boundary_ids_.begin(), boundary_ids_.end(), -1);
226
227 for (int f = 0; f < n_faces(); ++f)
228 {
229 const bool is_boundary = is_boundary_face(f);
230 std::vector<int> vs(n_face_vertices(f));
231 const auto p = face_barycenter(f);
232
233 for (int vid = 0; vid < vs.size(); ++vid)
234 vs[vid] = face_vertex(f, vid);
235
236 std::sort(vs.begin(), vs.end());
237 boundary_ids_[f] = marker(f, vs, p, is_boundary);
238
239 faces[valid_to_all_face(f)].boundary_id = boundary_ids_[f];
240 }
241 }
242
243 void NCMesh3D::compute_body_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &)> &marker)
244 {
245 body_ids_.resize(n_cells());
246 std::fill(body_ids_.begin(), body_ids_.end(), -1);
247
248 for (int e = 0; e < n_cells(); ++e)
249 {
250 const auto bary = cell_barycenter(e);
251 body_ids_[e] = marker(e, element_vertices(e), bary);
252 elements[valid_to_all_elem(e)].body_id = body_ids_[e];
253 }
254 }
255 void NCMesh3D::set_boundary_ids(const std::vector<int> &boundary_ids)
256 {
257 assert(boundary_ids.size() == n_faces());
258 Mesh::set_boundary_ids(boundary_ids);
259 for (int i = 0; i < boundary_ids.size(); i++)
260 {
261 faces[valid_to_all_face(i)].boundary_id = boundary_ids[i];
262 }
263 }
264 void NCMesh3D::set_body_ids(const std::vector<int> &body_ids)
265 {
266 assert(body_ids.size() == n_cells());
267 Mesh::set_body_ids(body_ids);
268 for (int i = 0; i < body_ids.size(); i++)
269 {
270 elements[valid_to_all_elem(i)].body_id = body_ids[i];
271 }
272 }
273
274 // void NCMesh3D::triangulate_faces(Eigen::MatrixXi &tris, Eigen::MatrixXd &pts, std::vector<int> &ranges) const
275 // {
276 // ranges.clear();
277
278 // std::vector<Eigen::MatrixXi> local_tris(n_cells());
279 // std::vector<Eigen::MatrixXd> local_pts(n_cells());
280 // Eigen::MatrixXi tets;
281
282 // int total_tris = 0;
283 // int total_pts = 0;
284
285 // ranges.push_back(0);
286
287 // Eigen::MatrixXd face_barys;
288 // face_barycenters(face_barys);
289
290 // Eigen::MatrixXd cell_barys;
291 // cell_barycenters(cell_barys);
292
293 // for (std::size_t e = 0; e < n_cells(); ++e)
294 // {
295 // const int n_vertices = n_cell_vertices(e);
296 // const int n_faces = n_cell_faces(e);
297
298 // Eigen::MatrixXd local_pt(n_vertices + n_faces, 3);
299
300 // std::map<int, int> global_to_local;
301
302 // for (int i = 0; i < n_vertices; ++i)
303 // {
304 // const int global_index = cell_vertex(e, i);
305 // local_pt.row(i) = point(global_index);
306 // global_to_local[global_index] = i;
307 // }
308
309 // int n_local_faces = 0;
310 // for (int i = 0; i < n_faces; ++i)
311 // {
312 // const int f_id = cell_face(e, i);
313 // n_local_faces += n_face_vertices(f_id);
314
315 // local_pt.row(n_vertices + i) = face_barys.row(f_id);
316 // }
317
318 // Eigen::MatrixXi local_faces(n_local_faces, 3);
319
320 // int face_index = 0;
321 // for (int i = 0; i < n_faces; ++i)
322 // {
323 // const int f_id = cell_face(e, i);
324
325 // const Eigen::RowVector3d e0 = (point(face_vertex(f_id, 0)) - local_pt.row(n_vertices + i));
326 // const Eigen::RowVector3d e1 = (point(face_vertex(f_id, 1)) - local_pt.row(n_vertices + i));
327 // const Eigen::RowVector3d normal = e0.cross(e1);
328 // // const Eigen::RowVector3d check_dir = (node_from_element(e)-p);
329 // const Eigen::RowVector3d check_dir = (cell_barys.row(e) - point(face_vertex(f_id, 1)));
330
331 // const bool reverse_order = normal.dot(check_dir) > 0;
332
333 // for (int j = 0; j < n_face_vertices(f_id); ++j)
334 // {
335 // const int jp = (j + 1) % n_face_vertices(f_id);
336 // if (reverse_order)
337 // {
338 // local_faces(face_index, 0) = global_to_local[face_vertex(f_id, jp)];
339 // local_faces(face_index, 1) = global_to_local[face_vertex(f_id, j)];
340 // }
341 // else
342 // {
343 // local_faces(face_index, 0) = global_to_local[face_vertex(f_id, j)];
344 // local_faces(face_index, 1) = global_to_local[face_vertex(f_id, jp)];
345 // }
346 // local_faces(face_index, 2) = n_vertices + i;
347
348 // ++face_index;
349 // }
350 // }
351
352 // local_pts[e] = local_pt;
353 // local_tris[e] = local_faces;
354
355 // total_tris += local_tris[e].rows();
356 // total_pts += local_pts[e].rows();
357
358 // ranges.push_back(total_tris);
359
360 // assert(local_pts[e].rows() == local_pt.rows());
361 // }
362
363 // tris.resize(total_tris, 3);
364 // pts.resize(total_pts, 3);
365
366 // int tri_index = 0;
367 // int pts_index = 0;
368 // for (std::size_t i = 0; i < local_tris.size(); ++i)
369 // {
370 // tris.block(tri_index, 0, local_tris[i].rows(), local_tris[i].cols()) = local_tris[i].array() + pts_index;
371 // tri_index += local_tris[i].rows();
372
373 // pts.block(pts_index, 0, local_pts[i].rows(), local_pts[i].cols()) = local_pts[i];
374 // pts_index += local_pts[i].rows();
375 // }
376 // }
377
378 RowVectorNd NCMesh3D::kernel(const int cell_id) const
379 {
380 assert(false);
381 return RowVectorNd();
382 }
384 {
386
387 idx.element = hi;
388
389 idx.element_patch = lf;
390 idx.face = cell_face(hi, lf);
391
392 if (lv >= 4)
393 lv = lv % 4;
394 idx.face_corner = lv;
395 idx.vertex = face_vertex(idx.face, idx.face_corner);
396
397 idx.edge = face_edge(idx.face, idx.face_corner);
398
399 return idx;
400 }
402 {
404
405 idx.element = hi;
406 idx.element_patch = 0;
407 idx.face = cell_face(hi, 0);
408 idx.face_corner = 0;
409 idx.vertex = face_vertex(idx.face, idx.face_corner);
410 idx.edge = face_edge(idx.face, 0);
411
412 return idx;
413 }
414
416 {
418
419 idx.element = hi;
420 idx.vertex = v0;
422
423 for (int i = 0; i < 4; i++)
424 {
425 const int f_id = cell_face(idx.element, i);
426 for (int j = 0; j < 3; j++)
427 {
428 const int e_id = face_edge(f_id, j);
429 if (idx.edge == e_id)
430 {
431 idx.element_patch = i;
432 idx.face = f_id;
433
434 for (int d = 0; d < n_face_vertices(f_id); d++)
435 if (face_vertex(f_id, d) == idx.vertex)
436 idx.face_corner = d;
437
438 assert(switch_vertex(idx).vertex == v1);
439
440 return idx;
441 }
442 }
443 }
444
445 assert(false);
446 return idx;
447 }
448 Navigation3D::Index NCMesh3D::get_index_from_element_face(int hi, int v0, int v1, int v2) const
449 {
451
452 idx.element = hi;
453 idx.vertex = v0;
455
456 for (int d = 0; d < n_face_vertices(idx.face); d++)
457 if (face_vertex(idx.face, d) == idx.vertex)
458 idx.face_corner = d;
459
460 int v0_ = v0, v1_ = v1;
461
462 // let v0_ < v1_
463 if (v0_ > v1_)
464 std::swap(v0_, v1_);
465
466 for (int i = 0; i < 4; i++)
467 {
468 const int fid = cell_face(idx.element, i);
469 if (fid != idx.face)
470 continue;
471
472 idx.element_patch = i;
473
474 for (int j = 0; j < 3; j++)
475 {
476 const int eid = face_edge(fid, j);
477 const int ev0 = edge_vertex(eid, 0);
478 const int ev1 = edge_vertex(eid, 1);
479
480 if ((ev0 == v0_ && ev1 == v1_) || (ev0 == v1_ && ev1 == v0_))
481 {
482 idx.edge = eid;
483
484 assert(switch_vertex(idx).vertex == v1);
485 assert(switch_vertex(switch_edge(idx)).vertex == v2);
486
487 return idx;
488 }
489 }
490 }
491
492 assert(false);
493 return idx;
494 }
495
496 std::vector<uint32_t> NCMesh3D::vertex_neighs(const int v_gid) const
497 {
498 std::vector<uint32_t> hs;
499 for (auto h : vertices[valid_to_all_vertex(v_gid)].elem_list)
500 hs.push_back(all_to_valid_elem(h));
501
502 return hs;
503 }
504 std::vector<uint32_t> NCMesh3D::edge_neighs(const int e_gid) const
505 {
506 std::vector<uint32_t> hs;
507 for (auto h : edges[valid_to_all_edge(e_gid)].elem_list)
508 hs.push_back(all_to_valid_elem(h));
509
510 return hs;
511 }
512
514 {
515 if (idx.vertex == edge_vertex(idx.edge, 0))
516 idx.vertex = edge_vertex(idx.edge, 1);
517 else
518 idx.vertex = edge_vertex(idx.edge, 0);
519
520 for (int d = 0; d < n_face_vertices(idx.face); d++)
521 if (face_vertex(idx.face, d) == idx.vertex)
522 idx.face_corner = d;
523
524 return idx;
525 }
527 {
528 if (idx.edge == face_edge(idx.face, idx.face_corner))
529 idx.edge = face_edge(idx.face, (idx.face_corner + 2) % 3);
530 else
531 idx.edge = face_edge(idx.face, idx.face_corner);
532 return idx;
533 }
535 {
536 for (int i = 0; i < 4; i++)
537 {
538 const int fid = cell_face(idx.element, i);
539 if (fid == idx.face)
540 continue;
541 if (idx.edge == face_edge(fid, 0) || idx.edge == face_edge(fid, 1) || idx.edge == face_edge(fid, 2))
542 {
543 idx.face = fid;
544 idx.element_patch = i;
545
546 for (int d = 0; d < n_face_vertices(fid); d++)
547 if (face_vertex(fid, d) == idx.vertex)
548 idx.face_corner = d;
549
550 break;
551 }
552 }
553 return idx;
554 }
556 {
557 const auto &face = faces[valid_to_all_face(idx.face)];
558 if (face.n_elem() != 2)
559 {
560 idx.element = -1;
561 return idx;
562 }
563 if (all_to_valid_elem(face.get_element()) == idx.element)
564 idx.element = all_to_valid_elem(face.find_opposite_element(face.get_element()));
565 else
566 idx.element = all_to_valid_elem(face.get_element());
567
568 for (int f = 0; f < n_cell_faces(idx.element); f++)
569 if (cell_face(idx.element, f) == idx.face)
570 idx.element_patch = f;
571 return idx;
572 }
573
582
583 void NCMesh3D::get_vertex_elements_neighs(const int v_id, std::vector<int> &ids) const
584 {
585 ids.clear();
586 for (auto h : vertices[valid_to_all_vertex(v_id)].elem_list)
587 ids.push_back(all_to_valid_elem(h));
588 }
589 void NCMesh3D::get_edge_elements_neighs(const int e_id, std::vector<int> &ids) const
590 {
591 ids.clear();
592 for (auto h : edges[valid_to_all_edge(e_id)].elem_list)
593 ids.push_back(all_to_valid_elem(h));
594 }
595 void NCMesh3D::get_face_elements_neighs(const int f_id, std::vector<int> &ids) const
596 {
597 ids.clear();
598 for (auto h : faces[valid_to_all_face(f_id)].elem_list)
599 ids.push_back(all_to_valid_elem(h));
600 }
601
602 void NCMesh3D::refine_element(int id_full)
603 {
604 assert(elements[id_full].is_valid());
605 if (elements[id_full].is_not_valid())
606 throw std::runtime_error("Cannot refine an invalid element!");
607
608 const auto v = elements[id_full].vertices;
609 elements[id_full].is_refined = true;
610 n_elements--;
611
612 for (int f = 0; f < elements[id_full].faces.size(); f++)
613 faces[elements[id_full].faces(f)].remove_element(id_full);
614
615 for (int e = 0; e < elements[id_full].edges.size(); e++)
616 edges[elements[id_full].edges(e)].remove_element(id_full);
617
618 for (int i = 0; i < v.size(); i++)
619 vertices[v(i)].remove_element(id_full);
620
621 if (elements[id_full].children(0) >= 0)
622 {
623 for (int c = 0; c < elements[id_full].children.size(); c++)
624 {
625 const int child_id = elements[id_full].children(c);
626 auto &elem = elements[child_id];
627 elem.is_ghost = false;
628 n_elements++;
629
630 for (int f = 0; f < elem.faces.size(); f++)
631 faces[elem.faces(f)].add_element(child_id);
632
633 for (int e = 0; e < elem.edges.size(); e++)
634 edges[elem.edges(e)].add_element(child_id);
635
636 for (int v = 0; v < elem.vertices.size(); v++)
637 vertices[elem.vertices(v)].add_element(child_id);
638 }
639 }
640 else
641 {
642 // create mid-points if not exist
643 const int v1 = v[0];
644 const int v2 = v[1];
645 const int v3 = v[2];
646 const int v4 = v[3];
647 const int v5 = get_vertex(Eigen::Vector2i(v1, v2));
648 const int v8 = get_vertex(Eigen::Vector2i(v3, v2));
649 const int v6 = get_vertex(Eigen::Vector2i(v1, v3));
650 const int v7 = get_vertex(Eigen::Vector2i(v1, v4));
651 const int v9 = get_vertex(Eigen::Vector2i(v4, v2));
652 const int v10 = get_vertex(Eigen::Vector2i(v3, v4));
653
654 // inherite line singularity flag from parent edge
655 for (int i = 0; i < v.size(); i++)
656 for (int j = 0; j < i; j++)
657 {
658 int mid_id = find_vertex(v[i], v[j]);
659 int edge_id = find_edge(v[i], v[j]);
660 int edge1 = get_edge(v[i], mid_id);
661 int edge2 = get_edge(v[j], mid_id);
662 edges[edge1].boundary_id = edges[edge_id].boundary_id;
663 edges[edge2].boundary_id = edges[edge_id].boundary_id;
664 }
665
666 for (int i = 0; i < v.size(); i++)
667 for (int j = 0; j < i; j++)
668 for (int k = 0; k < j; k++)
669 {
670 int fid = find_face(v[i], v[j], v[k]);
671 int vij = find_vertex(v[i], v[j]);
672 int vjk = find_vertex(v[j], v[k]);
673 int vik = find_vertex(v[i], v[k]);
674 int facei = get_face(v[i], vij, vik);
675 int facej = get_face(v[j], vjk, vij);
676 int facek = get_face(v[k], vjk, vik);
677 int facem = get_face(vij, vjk, vik);
678 faces[facei].boundary_id = faces[fid].boundary_id;
679 faces[facej].boundary_id = faces[fid].boundary_id;
680 faces[facek].boundary_id = faces[fid].boundary_id;
681 faces[facem].boundary_id = faces[fid].boundary_id;
682 }
683
684 // create children
685 elements[id_full].children(0) = elements.size();
686 add_element(Eigen::Vector4i(v1, v5, v6, v7), id_full);
687 elements[id_full].children(1) = elements.size();
688 add_element(Eigen::Vector4i(v5, v2, v8, v9), id_full);
689 elements[id_full].children(2) = elements.size();
690 add_element(Eigen::Vector4i(v6, v8, v3, v10), id_full);
691 elements[id_full].children(3) = elements.size();
692 add_element(Eigen::Vector4i(v7, v9, v10, v4), id_full);
693 elements[id_full].children(4) = elements.size();
694 add_element(Eigen::Vector4i(v5, v6, v7, v9), id_full);
695 elements[id_full].children(5) = elements.size();
696 add_element(Eigen::Vector4i(v5, v9, v8, v6), id_full);
697 elements[id_full].children(6) = elements.size();
698 add_element(Eigen::Vector4i(v6, v7, v9, v10), id_full);
699 elements[id_full].children(7) = elements.size();
700 add_element(Eigen::Vector4i(v6, v10, v9, v8), id_full);
701 }
702
703 refineHistory.push_back(id_full);
704 }
705 void NCMesh3D::refine_elements(const std::vector<int> &ids)
706 {
707 std::vector<int> full_ids(ids.size());
708 for (int i = 0; i < ids.size(); i++)
709 full_ids[i] = valid_to_all_elem(ids[i]);
710
711 for (int i : full_ids)
713 }
714
716 {
717 const int parent_id = elements[id_full].parent;
718 auto &parent = elements[parent_id];
719
720 for (int i = 0; i < parent.children.size(); i++)
721 if (elements[parent.children(i)].is_not_valid())
722 throw std::runtime_error("Invalid siblings in coarsening!");
723
724 // remove elements
725 for (int c = 0; c < parent.children.size(); c++)
726 {
727 auto &elem = elements[parent.children(c)];
728 elem.is_ghost = true;
729 n_elements--;
730
731 for (int f = 0; f < elem.faces.size(); f++)
732 faces[elem.faces(f)].remove_element(parent.children(c));
733
734 for (int e = 0; e < elem.edges.size(); e++)
735 edges[elem.edges(e)].remove_element(parent.children(c));
736
737 for (int v = 0; v < elem.vertices.size(); v++)
738 vertices[elem.vertices(v)].remove_element(parent.children(c));
739 }
740
741 // add element
742 parent.is_refined = false;
743 n_elements++;
744
745 for (int f = 0; f < parent.faces.size(); f++)
746 faces[parent.faces(f)].add_element(parent_id);
747
748 for (int e = 0; e < parent.edges.size(); e++)
749 edges[parent.edges(e)].add_element(parent_id);
750
751 for (int v = 0; v < parent.vertices.size(); v++)
752 vertices[parent.vertices(v)].add_element(parent_id);
753
754 refineHistory.push_back(parent_id);
755 }
756
758 {
759 for (auto &face : faces)
760 {
761 if (face.n_elem() == 1)
762 face.isboundary = true;
763 else
764 face.isboundary = false;
765 }
766
767 for (auto &face : faces)
768 {
769 if (face.leader >= 0 && face.n_elem() > 0 && faces[face.leader].n_elem() > 0)
770 {
771 face.isboundary = false;
772 faces[face.leader].isboundary = false;
773 }
774 }
775
776 for (auto &vert : vertices)
777 vert.isboundary = false;
778
779 for (auto &edge : edges)
780 edge.isboundary = false;
781
782 for (auto &face : faces)
783 {
784 if (face.isboundary && face.n_elem())
785 {
786 for (int j = 0; j < 3; j++)
787 vertices[face.vertices(j)].isboundary = true;
788
789 for (int j = 0; j < 3; j++)
790 for (int i = 0; i < j; i++)
791 edges[find_edge(face.vertices(i), face.vertices(j))].isboundary = true;
792 }
793 }
794 }
795
797 {
798 all_to_valid_elemMap.assign(elements.size(), -1);
800
801 for (int i = 0, e = 0; i < elements.size(); i++)
802 {
803 if (elements[i].is_not_valid())
804 continue;
807 e++;
808 }
809
810 const int n_verts = n_vertices();
811
812 all_to_valid_vertexMap.assign(vertices.size(), -1);
813 valid_to_all_vertexMap.resize(n_verts);
814
815 for (int i = 0, j = 0; i < vertices.size(); i++)
816 {
817 if (vertices[i].n_elem() == 0)
818 continue;
821 j++;
822 }
823
824 all_to_valid_edgeMap.assign(edges.size(), -1);
826
827 for (int i = 0, j = 0; i < edges.size(); i++)
828 {
829 if (edges[i].n_elem() == 0)
830 continue;
833 j++;
834 }
835
836 all_to_valid_faceMap.assign(faces.size(), -1);
838
839 for (int i = 0, j = 0; i < faces.size(); i++)
840 {
841 if (faces[i].n_elem() == 0)
842 continue;
845 j++;
846 }
847 index_prepared = true;
848 }
849
850 void NCMesh3D::append(const Mesh &mesh)
851 {
852 assert(typeid(mesh) == typeid(NCMesh3D));
853 Mesh::append(mesh);
854
855 const NCMesh3D &mesh3d = dynamic_cast<const NCMesh3D &>(mesh);
856
857 const int n_v = n_vertices();
858 const int n_f = n_cells();
859
860 vertices.reserve(n_v + mesh3d.n_vertices());
861 for (int i = 0; i < mesh3d.n_vertices(); i++)
862 {
863 vertices.emplace_back(mesh3d.vertices[i].pos);
864 }
865 for (int i = 0; i < mesh3d.n_cells(); i++)
866 {
867 Eigen::Vector4i cell = mesh3d.elements[i].vertices;
868 cell = cell.array() + n_v;
869 add_element(cell, -1);
870 }
871
872 prepare_mesh();
873 }
874
875 std::unique_ptr<Mesh> NCMesh3D::copy() const
876 {
877 return std::make_unique<NCMesh3D>(*this);
878 }
879
880 int NCMesh3D::find_vertex(Eigen::Vector2i v) const
881 {
882 std::sort(v.data(), v.data() + v.size());
883 auto search = midpointMap.find(v);
884 if (search != midpointMap.end())
885 return search->second;
886 else
887 return -1;
888 }
889 int NCMesh3D::get_vertex(Eigen::Vector2i v)
890 {
891 std::sort(v.data(), v.data() + v.size());
892 int id = find_vertex(v);
893 if (id < 0)
894 {
895 Eigen::VectorXd v_mid = (vertices[v[0]].pos + vertices[v[1]].pos) / 2.;
896 id = vertices.size();
897 vertices.emplace_back(v_mid);
898 midpointMap.emplace(v, id);
899 }
900 return id;
901 }
902 int NCMesh3D::find_edge(Eigen::Vector2i v) const
903 {
904 std::sort(v.data(), v.data() + v.size());
905 auto search = edgeMap.find(v);
906 if (search != edgeMap.end())
907 return search->second;
908 else
909 return -1;
910 }
911 int NCMesh3D::get_edge(Eigen::Vector2i v)
912 {
913 std::sort(v.data(), v.data() + v.size());
914 int id = find_edge(v);
915 if (id < 0)
916 {
917 edges.emplace_back(v);
918 id = edges.size() - 1;
919 edgeMap.emplace(v, id);
920 }
921 return id;
922 }
923 int NCMesh3D::find_face(Eigen::Vector3i v) const
924 {
925 std::sort(v.data(), v.data() + v.size());
926 auto search = faceMap.find(v);
927 if (search != faceMap.end())
928 return search->second;
929 else
930 return -1;
931 }
932 int NCMesh3D::get_face(Eigen::Vector3i v)
933 {
934 std::sort(v.data(), v.data() + v.size());
935 int id = find_face(v);
936 if (id < 0)
937 {
938 faces.emplace_back(v);
939 id = faces.size() - 1;
940 faceMap.emplace(v, id);
941 }
942 return id;
943 }
944 void NCMesh3D::traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector<follower_edge> &list) const
945 {
946 int v_mid = find_vertex(v);
947 std::vector<follower_edge> list1, list2;
948 if (v_mid >= 0)
949 {
950 double p_mid = (p1 + p2) / 2;
951 traverse_edge(Eigen::Vector2i(v[0], v_mid), p1, p_mid, depth + 1, list1);
952 list.insert(
953 list.end(),
954 std::make_move_iterator(list1.begin()),
955 std::make_move_iterator(list1.end()));
956 traverse_edge(Eigen::Vector2i(v_mid, v[1]), p_mid, p2, depth + 1, list2);
957 list.insert(
958 list.end(),
959 std::make_move_iterator(list2.begin()),
960 std::make_move_iterator(list2.end()));
961 }
962 if (depth > 0)
963 {
964 int follower_id = find_edge(v);
965 if (follower_id >= 0 && edges[follower_id].n_elem() > 0)
966 list.emplace_back(follower_id, p1, p2);
967 }
968 }
970 {
971 for (auto &edge : edges)
972 {
973 edge.leader = -1;
974 edge.followers.clear();
975 edge.weights.setConstant(-1);
976 }
977
978 for (int e_id = 0; e_id < edges.size(); e_id++)
979 {
980 auto &edge = edges[e_id];
981 if (edge.n_elem() == 0)
982 continue;
983 std::vector<follower_edge> followers;
984 traverse_edge(edge.vertices, 0, 1, 0, followers);
985 for (auto &s : followers)
986 {
987 if (edges[s.id].leader >= 0 && std::abs(edges[s.id].weights(1) - edges[s.id].weights(0)) < std::abs(s.p2 - s.p1))
988 continue;
989 edge.followers.push_back(s.id);
990 edges[s.id].leader = e_id;
991 edges[s.id].weights << s.p1, s.p2;
992 }
993 }
994
995 // In 3d, it's possible for one edge to have both leader and follower edges, but we don't care this case.
996 for (auto &edge : edges)
997 if (edge.leader >= 0 && edge.followers.size())
998 edge.followers.clear();
999 }
1000 void NCMesh3D::traverse_face(int v1, int v2, int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3, int depth, std::vector<follower_face> &face_list, std::vector<int> &edge_list) const
1001 {
1002 int v12 = find_vertex(Eigen::Vector2i(v1, v2));
1003 int v23 = find_vertex(Eigen::Vector2i(v3, v2));
1004 int v31 = find_vertex(Eigen::Vector2i(v1, v3));
1005 std::vector<follower_face> list1, list2, list3, list4;
1006 std::vector<int> list1_, list2_, list3_, list4_;
1007 if (depth > 0)
1008 {
1009 edge_list.push_back(find_edge(v1, v2));
1010 edge_list.push_back(find_edge(v3, v2));
1011 edge_list.push_back(find_edge(v1, v3));
1012 }
1013 if (v12 >= 0 && v23 >= 0 && v31 >= 0)
1014 {
1015 auto p12 = (p1 + p2) / 2, p23 = (p2 + p3) / 2, p31 = (p1 + p3) / 2;
1016 traverse_face(v1, v12, v31, p1, p12, p31, depth + 1, list1, list1_);
1017 traverse_face(v12, v2, v23, p12, p2, p23, depth + 1, list2, list2_);
1018 traverse_face(v31, v23, v3, p31, p23, p3, depth + 1, list3, list3_);
1019 traverse_face(v12, v23, v31, p12, p23, p31, depth + 1, list4, list4_);
1020
1021 face_list.insert(face_list.end(), std::make_move_iterator(list1.begin()), std::make_move_iterator(list1.end()));
1022 face_list.insert(face_list.end(), std::make_move_iterator(list2.begin()), std::make_move_iterator(list2.end()));
1023 face_list.insert(face_list.end(), std::make_move_iterator(list3.begin()), std::make_move_iterator(list3.end()));
1024 face_list.insert(face_list.end(), std::make_move_iterator(list4.begin()), std::make_move_iterator(list4.end()));
1025
1026 edge_list.insert(edge_list.end(), std::make_move_iterator(list1_.begin()), std::make_move_iterator(list1_.end()));
1027 edge_list.insert(edge_list.end(), std::make_move_iterator(list2_.begin()), std::make_move_iterator(list2_.end()));
1028 edge_list.insert(edge_list.end(), std::make_move_iterator(list3_.begin()), std::make_move_iterator(list3_.end()));
1029 edge_list.insert(edge_list.end(), std::make_move_iterator(list4_.begin()), std::make_move_iterator(list4_.end()));
1030 }
1031 if (depth > 0)
1032 {
1033 int follower_id = find_face(Eigen::Vector3i(v1, v2, v3));
1034 if (follower_id >= 0 && faces[follower_id].n_elem() > 0)
1035 face_list.emplace_back(follower_id, p1, p2, p3);
1036 }
1037 }
1039 {
1040 Eigen::Matrix<int, 4, 3> fv;
1041 fv.row(0) << 0, 1, 2;
1042 fv.row(1) << 0, 1, 3;
1043 fv.row(2) << 1, 2, 3;
1044 fv.row(3) << 2, 0, 3;
1045
1046 for (auto &face : faces)
1047 {
1048 face.leader = -1;
1049 face.followers.clear();
1050 }
1051
1052 for (auto &edge : edges)
1053 {
1054 edge.leader_face = -1;
1055 }
1056
1057 for (int f_id = 0; f_id < faces.size(); f_id++)
1058 {
1059 auto &face = faces[f_id];
1060 if (face.n_elem() == 0)
1061 continue;
1062 std::vector<follower_face> followers;
1063 std::vector<int> interior_edges;
1064 traverse_face(face.vertices(0), face.vertices(1), face.vertices(2), Eigen::Vector2d(0, 0), Eigen::Vector2d(1, 0), Eigen::Vector2d(0, 1), 0, followers, interior_edges); // order is important
1065 for (auto &s : followers)
1066 {
1067 faces[s.id].leader = f_id;
1068 face.followers.push_back(s.id);
1069 }
1070 for (int s : interior_edges)
1071 if (s >= 0 && edges[s].leader < 0 && edges[s].n_elem() > 0)
1072 edges[s].leader_face = f_id;
1073 }
1074 }
1076 {
1077 for (auto &vert : vertices)
1078 {
1079 vert.edge = -1;
1080 vert.face = -1;
1081 }
1082
1083 for (auto &small_edge : edges)
1084 {
1085 // invalid edges
1086 if (small_edge.n_elem() == 0)
1087 continue;
1088
1089 // not follower edges
1090 int large_edge = small_edge.leader;
1091 if (large_edge < 0)
1092 continue;
1093 assert(edges[large_edge].leader < 0);
1094
1095 // follower edges
1096 for (int j = 0; j < 2; j++)
1097 {
1098 const int v_id = small_edge.vertices(j);
1099 // hanging nodes
1100 if (v_id != edges[large_edge].vertices(0) && v_id != edges[large_edge].vertices(1))
1101 vertices[v_id].edge = large_edge;
1102 }
1103 }
1104
1105 for (auto &small_face : faces)
1106 {
1107 // invalid faces
1108 if (small_face.n_elem() == 0)
1109 continue;
1110
1111 // not follower faces
1112 int large_face = small_face.leader;
1113 if (large_face < 0)
1114 continue;
1115
1116 // follower faces
1117 for (int j = 0; j < 3; j++)
1118 {
1119 const int v_id = small_face.vertices(j);
1120 // hanging nodes
1121 if (v_id != faces[large_face].vertices(0) && v_id != faces[large_face].vertices(1) && v_id != faces[large_face].vertices(2))
1122 vertices[v_id].face = large_face;
1123 }
1124 }
1125 }
1126 std::array<int, 4> NCMesh3D::get_ordered_vertices_from_tet(const int element_index) const
1127 {
1128 return std::array<int, 4>({{cell_vertex(element_index, 0), cell_vertex(element_index, 1), cell_vertex(element_index, 2), cell_vertex(element_index, 3)}});
1129 }
1130 int NCMesh3D::add_element(Eigen::Vector4i v, int parent)
1131 {
1132 const int id = elements.size();
1133 const int level = (parent < 0) ? 0 : elements[parent].level + 1;
1134
1135 Eigen::Vector3d e1 = vertices[v[1]].pos - vertices[v[0]].pos;
1136 Eigen::Vector3d e2 = vertices[v[2]].pos - vertices[v[0]].pos;
1137 Eigen::Vector3d e3 = vertices[v[3]].pos - vertices[v[0]].pos;
1138 if ((e1.cross(e2)).dot(e3) < 0)
1139 std::swap(v[2], v[3]);
1140
1141 e2 = vertices[v[2]].pos - vertices[v[0]].pos;
1142 e3 = vertices[v[3]].pos - vertices[v[0]].pos;
1143 assert((e1.cross(e2)).dot(e3) > 0);
1144
1145 elements.emplace_back(3, v, level, parent);
1146
1147 if (parent >= 0)
1148 elements[id].body_id = elements[parent].body_id;
1149
1150 // add faces if not exist
1151 const int face012 = get_face(v[0], v[1], v[2]);
1152 const int face013 = get_face(v[0], v[1], v[3]);
1153 const int face123 = get_face(v[1], v[2], v[3]);
1154 const int face203 = get_face(v[2], v[0], v[3]);
1155
1156 faces[face012].add_element(id);
1157 faces[face013].add_element(id);
1158 faces[face123].add_element(id);
1159 faces[face203].add_element(id);
1160
1161 elements[id].faces << face012, face013, face123, face203;
1162
1163 // add edges if not exist
1164 const int edge01 = get_edge(v[0], v[1]);
1165 const int edge12 = get_edge(v[1], v[2]);
1166 const int edge20 = get_edge(v[2], v[0]);
1167 const int edge03 = get_edge(v[0], v[3]);
1168 const int edge13 = get_edge(v[1], v[3]);
1169 const int edge23 = get_edge(v[2], v[3]);
1170
1171 edges[edge01].add_element(id);
1172 edges[edge12].add_element(id);
1173 edges[edge20].add_element(id);
1174 edges[edge03].add_element(id);
1175 edges[edge13].add_element(id);
1176 edges[edge23].add_element(id);
1177
1178 elements[id].edges << edge01, edge12, edge20, edge03, edge13, edge23;
1179
1180 n_elements++;
1181
1182 for (int i = 0; i < v.size(); i++)
1183 vertices[v[i]].add_element(id);
1184
1185 return id;
1186 }
1187 } // namespace mesh
1188} // namespace polyfem
int V
Eigen::RowVectorXd point
int edge_id
Format-independent input used to construct a runtime Mesh.
Definition MeshData.hpp:12
Eigen::MatrixXd vertices
Definition MeshData.hpp:21
bool has_polyhedral_topology() const
Definition MeshData.hpp:19
Eigen::MatrixXi elements
Definition MeshData.hpp:22
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
std::vector< ElementType > elements_tag_
list of element types
Definition Mesh.hpp:686
bool has_boundary_ids() const
checks if surface selections are available
Definition Mesh.hpp:528
bool has_node_ids() const
checks if points selections are available
Definition Mesh.hpp:524
virtual void set_body_ids(const std::vector< int > &body_ids)
Set the volume sections.
Definition Mesh.hpp:444
std::vector< int > boundary_ids_
list of surface labels
Definition Mesh.hpp:690
void clear_higher_order_data()
Definition Mesh.cpp:685
std::vector< int > node_ids_
list of node labels
Definition Mesh.hpp:688
std::vector< int > element_vertices(const int el_id) const
list of vids of an element
Definition Mesh.hpp:216
std::vector< int > body_ids_
list of volume labels
Definition Mesh.hpp:692
virtual int get_default_boundary_id(const int primitive) const
Get the default boundary selection of an element (face in 3d, edge in 2d)
Definition Mesh.hpp:454
void filter_element_data(const std::vector< bool > &keep)
Definition Mesh.cpp:46
virtual void append(const Mesh &mesh)
appends a new mesh to the end of this
Definition Mesh.cpp:456
virtual void set_boundary_ids(const std::vector< int > &boundary_ids)
Set the boundary selection from a vector.
Definition Mesh.hpp:436
void remove_elements(const std::vector< bool > &keep) override
Remove all top-dimensional elements whose mask entry is false.
Definition NCMesh3D.cpp:18
int find_vertex(Eigen::Vector2i v) const
Definition NCMesh3D.cpp:880
bool is_boundary_element(const int element_global_id) const override
is cell boundary
Definition NCMesh3D.cpp:92
void compute_body_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &)> &marker) override
computes boundary selections based on a function
Definition NCMesh3D.cpp:243
std::vector< int > all_to_valid_elemMap
Definition NCMesh3D.hpp:472
int n_faces() const override
number of faces
Definition NCMesh3D.hpp:189
int valid_to_all_edge(const int id) const
Definition NCMesh3D.hpp:396
Navigation3D::Index next_around_edge(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:574
int face_edge(const int f_id, const int le_id) const
Definition NCMesh3D.cpp:67
int n_cell_faces(const int c_id) const override
Definition NCMesh3D.hpp:219
void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector< follower_edge > &list) const
Definition NCMesh3D.cpp:944
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > midpointMap
Definition NCMesh3D.hpp:468
int n_cells() const override
number of cells
Definition NCMesh3D.hpp:188
void build_element_vertex_adjacency()
void prepare_mesh() override
method used to finalize the mesh.
Definition NCMesh3D.hpp:339
std::vector< ncBoundary > edges
Definition NCMesh3D.hpp:465
int valid_to_all_face(const int id) const
Definition NCMesh3D.hpp:408
void bounding_box(RowVectorNd &min, RowVectorNd &max) const override
computes the bbox of the mesh
Definition NCMesh3D.cpp:205
void append(const Mesh &mesh) override
appends a new mesh to the end of this
Definition NCMesh3D.cpp:850
std::vector< int > refineHistory
Definition NCMesh3D.hpp:477
double edge_length(const int gid) const override
edge length
Definition NCMesh3D.cpp:163
int n_edges() const override
number of edges
Definition NCMesh3D.hpp:197
void compute_boundary_ids(const std::function< int(const size_t, const std::vector< int > &, const RowVectorNd &, bool)> &marker) override
computes boundary selections based on a function
Definition NCMesh3D.cpp:222
int get_edge(Eigen::Vector2i v)
Definition NCMesh3D.cpp:911
void set_point(const int global_index, const RowVectorNd &p) override
Set the point.
Definition NCMesh3D.cpp:176
int add_element(Eigen::Vector4i v, int parent=-1)
int get_face(Eigen::Vector3i v)
Definition NCMesh3D.cpp:932
void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector< std::vector< int > > &nodes) override
attach high order nodes
Definition NCMesh3D.cpp:136
int n_face_vertices(const int f_id) const override
number of vertices of a face
Definition NCMesh3D.hpp:214
RowVectorNd cell_barycenter(const int c) const override
cell barycenter
Definition NCMesh3D.cpp:196
std::vector< uint32_t > edge_neighs(const int e_gid) const override
Definition NCMesh3D.cpp:504
int all_to_valid_elem(const int id) const
Definition NCMesh3D.hpp:415
int n_vertices() const override
number of vertices
Definition NCMesh3D.hpp:205
std::vector< ncVert > vertices
Definition NCMesh3D.hpp:464
Navigation3D::Index get_index_from_element_edge(int hi, int v0, int v1) const override
Definition NCMesh3D.cpp:415
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > edgeMap
Definition NCMesh3D.hpp:469
void traverse_face(int v1, int v2, int v3, Eigen::Vector2d p1, Eigen::Vector2d p2, Eigen::Vector2d p3, int depth, std::vector< follower_face > &face_list, std::vector< int > &edge_list) const
void refine(const int n_refinement, const double t) override
refine the mesh
Definition NCMesh3D.cpp:75
void normalize() override
normalize the mesh
Definition NCMesh3D.cpp:143
std::vector< int > all_to_valid_vertexMap
Definition NCMesh3D.hpp:473
int all_to_valid_edge(const int id) const
Definition NCMesh3D.hpp:391
bool build_topology(const MeshData &data) override
Construct only the dimension-specific topology.
Definition NCMesh3D.cpp:102
void get_face_elements_neighs(const int f_id, std::vector< int > &ids) const
Definition NCMesh3D.cpp:595
std::unique_ptr< Mesh > copy() const override
Create a copy of the mesh.
Definition NCMesh3D.cpp:875
int valid_to_all_elem(const int id) const
Definition NCMesh3D.hpp:420
void refine_element(int id_full)
Definition NCMesh3D.cpp:602
Navigation3D::Index switch_vertex(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:513
RowVectorNd kernel(const int cell_id) const override
Definition NCMesh3D.cpp:378
bool is_boundary_vertex(const int vertex_global_id) const override
is vertex boundary
Definition NCMesh3D.hpp:230
int cell_face(const int c_id, const int lf_id) const override
Definition NCMesh3D.hpp:221
void compute_elements_tag() override
compute element types, see ElementType
Definition NCMesh3D.cpp:155
RowVectorNd point(const int global_index) const override
point coordinates
Definition NCMesh3D.cpp:171
std::vector< int > all_to_valid_edgeMap
Definition NCMesh3D.hpp:474
int find_edge(Eigen::Vector2i v) const
Definition NCMesh3D.cpp:902
Navigation3D::Index get_index_from_element(int hi, int lf, int lv) const override
Definition NCMesh3D.cpp:383
bool is_boundary_face(const int face_global_id) const override
is face boundary
Definition NCMesh3D.hpp:232
int cell_vertex(const int f_id, const int lv_id) const override
id of the vertex of a cell
Definition NCMesh3D.hpp:220
std::vector< int > all_to_valid_faceMap
Definition NCMesh3D.hpp:475
void coarsen_element(int id_full)
Definition NCMesh3D.cpp:715
Navigation3D::Index next_around_face(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:578
std::vector< int > valid_to_all_elemMap
Definition NCMesh3D.hpp:472
std::vector< int > valid_to_all_edgeMap
Definition NCMesh3D.hpp:474
RowVectorNd face_barycenter(const int f) const override
face barycenter
Definition NCMesh3D.cpp:188
int n_cell_edges(const int c_id) const override
Definition NCMesh3D.hpp:218
Navigation3D::Index switch_element(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:555
void get_vertex_elements_neighs(const int v_id, std::vector< int > &ids) const override
Definition NCMesh3D.cpp:583
std::vector< ncElem > elements
Definition NCMesh3D.hpp:463
std::unordered_map< Eigen::Vector3i, int, ArrayHasher3D > faceMap
Definition NCMesh3D.hpp:470
RowVectorNd edge_barycenter(const int e) const override
edge barycenter
Definition NCMesh3D.cpp:181
std::vector< int > valid_to_all_faceMap
Definition NCMesh3D.hpp:475
std::vector< uint32_t > vertex_neighs(const int v_gid) const override
Definition NCMesh3D.cpp:496
std::vector< int > valid_to_all_vertexMap
Definition NCMesh3D.hpp:473
std::array< int, 4 > get_ordered_vertices_from_tet(const int element_index) const override
void update_elements_tag() override
Update elements types.
Definition NCMesh3D.cpp:159
int valid_to_all_vertex(const int id) const
Definition NCMesh3D.hpp:384
int edge_vertex(const int e_id, const int lv_id) const override
id of the edge vertex
Definition NCMesh3D.hpp:226
void refine_elements(const std::vector< int > &ids)
Definition NCMesh3D.cpp:705
int get_vertex(Eigen::Vector2i v)
Definition NCMesh3D.cpp:889
int find_face(Eigen::Vector3i v) const
Definition NCMesh3D.cpp:923
void get_edge_elements_neighs(const int e_id, std::vector< int > &ids) const override
Definition NCMesh3D.cpp:589
Navigation3D::Index switch_face(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:534
int face_vertex(const int f_id, const int lv_id) const override
id of the face vertex
Definition NCMesh3D.hpp:224
int all_to_valid_face(const int id) const
Definition NCMesh3D.hpp:403
Navigation3D::Index get_index_from_element_face(int hi, int v0, int v1, int v2) const override
Definition NCMesh3D.cpp:448
void set_body_ids(const std::vector< int > &body_ids) override
Set the volume sections.
Definition NCMesh3D.cpp:264
void set_boundary_ids(const std::vector< int > &boundary_ids) override
Set the boundary selection from a vector.
Definition NCMesh3D.cpp:255
std::vector< ncBoundary > faces
Definition NCMesh3D.hpp:466
Navigation3D::Index switch_edge(Navigation3D::Index idx) const override
Definition NCMesh3D.cpp:526
std::tuple< bool, int, Tree > is_valid(const int dim, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &gbases, const Eigen::VectorXd &u, const double threshold, const unsigned max_iter)
Definition Jacobian.cpp:201
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:13