PolyFEM
Loading...
Searching...
No Matches
NCMesh2D.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace polyfem
6{
7 namespace mesh
8 {
9 class NCMesh2D : public Mesh2D
10 {
11 public:
13 {
14 int id;
15 double p1, p2;
16
17 follower_edge(int id_, double p1_, double p2_)
18 {
19 id = id_;
20 p1 = p1_;
21 p2 = p2_;
22 }
23 };
24
26 {
27 int id;
28 Eigen::Vector2d p1, p2, p3;
29
30 follower_face(int id_, Eigen::Vector2d p1_, Eigen::Vector2d p2_, Eigen::Vector2d p3_)
31 {
32 id = id_;
33 p1 = p1_;
34 p2 = p2_;
35 p3 = p3_;
36 }
37 };
38
39 struct ncVert
40 {
41 ncVert(const Eigen::VectorXd pos_) : pos(pos_){};
43
44 Eigen::VectorXd pos;
45 bool isboundary = false;
46
47 int edge = -1; // only used if the vertex is on the interior of an edge
48 int face = -1; // only 3d, only used if the vertex is on the interior of an face
49
50 double weight = -1.; // only 2d, the local position of this vertex on the edge
51
52 int n_elem = 0; // number of valid elements that share this vertex
53 };
54
56 {
57 ncBoundary(const Eigen::VectorXi vert) : vertices(vert)
58 {
59 weights.setConstant(-1);
60 };
62
63 int n_elem() const
64 {
65 return elem_list.size();
66 }
67
68 void add_element(const int e)
69 {
70 elem_list.insert(e);
71 };
72
73 void remove_element(const int e)
74 {
75 int num = elem_list.erase(e);
76 assert(num == 1);
77 }
78
79 int get_element() const
80 {
81 assert(n_elem() > 0);
82 auto it = elem_list.cbegin();
83 return *it;
84 }
85
86 int find_opposite_element(int e) const
87 {
88 assert(n_elem() == 2);
89 bool exist = false;
90 int oppo = -1;
91 for (int elem : elem_list)
92 if (elem == e)
93 exist = true;
94 else
95 oppo = elem;
96
97 assert(oppo >= 0);
98 assert(exist);
99 return oppo;
100 }
101
102 std::set<int> elem_list; // elements that contain this edge/face
103 Eigen::VectorXi vertices;
104
105 bool isboundary = false; // valid only after calling mark_boundary()
106 int boundary_id = -1;
107
108 int leader = -1; // if this edge/face lies on a larger edge/face
109 std::vector<int> followers; // followers of this edge/face
110
111 int leader_face = -1; // if this edge lies in the interior of a face
112
113 std::vector<int> global_ids; // only used for building basis
114
115 // the following only used if it's an edge
116 Eigen::Vector2d weights; // position of this edge on its leader edge
117 };
118
119 struct ncElem
120 {
121 ncElem(const int dim_, const Eigen::VectorXi vertices_, const int level_, const int parent_) : dim(dim_), level(level_), parent(parent_), geom_vertices(vertices_)
122 {
124
125 assert(geom_vertices.size() == dim + 1);
126 edges.setConstant(3 * (dim - 1), 1, -1);
127 faces.setConstant(4 * (dim - 2), 1, -1);
128 children.setConstant(std::round(pow(2, dim)), 1, -1);
129 };
131
132 bool is_valid() const
133 {
134 return (!is_ghost) && (!is_refined);
135 };
136
137 bool is_not_valid() const
138 {
139 return is_ghost || is_refined;
140 };
141
142 int dim;
143 int level; // level of refinement
145 Eigen::VectorXi geom_vertices;
146
147 Eigen::VectorXi vertices; // geom_vertices with a different order that used in polyfem
148
149 Eigen::VectorXi edges;
150 Eigen::VectorXi faces;
151 Eigen::VectorXi children;
152
154
155 bool is_refined = false;
156 bool is_ghost = false;
157 };
158
159 NCMesh2D() = default;
160 virtual ~NCMesh2D() = default;
161 NCMesh2D(NCMesh2D &&) = default;
163 NCMesh2D(const NCMesh2D &) = default;
164 NCMesh2D &operator=(const NCMesh2D &) = default;
165
166 bool is_conforming() const override { return false; }
167
168 int n_faces() const override { return n_elements; }
169 int n_edges() const override
170 {
171 int n = 0;
172 for (const auto &edge : edges)
173 if (edge.n_elem())
174 n++;
175 return n;
176 }
177 int n_vertices() const override
178 {
179 int n_verts = 0;
180 for (const auto &vert : vertices)
181 if (vert.n_elem)
182 n_verts++;
183
184 return n_verts;
185 }
186
187 inline int n_face_vertices(const int f_id) const override { return 3; }
188
189 inline int face_ref_level(const int f_id) const { return elements[valid_to_all_elem(f_id)].level; }
190
191 int face_vertex(const int f_id, const int lv_id) const override { return all_to_valid_vertex(elements[valid_to_all_elem(f_id)].vertices(lv_id)); }
192 int edge_vertex(const int e_id, const int lv_id) const override { return all_to_valid_vertex(edges[valid_to_all_edge(e_id)].vertices(lv_id)); }
193 int cell_vertex(const int f_id, const int lv_id) const override { return all_to_valid_vertex(elements[valid_to_all_elem(f_id)].vertices(lv_id)); }
194
195 int face_edge(const int f_id, const int le_id) const { return all_to_valid_edge(elements[valid_to_all_elem(f_id)].edges(le_id)); }
196 int leader_edge_of_vertex(const int v_id) const
197 {
198 assert(adj_prepared);
199 return (vertices[valid_to_all_vertex(v_id)].edge < 0) ? -1 : all_to_valid_edge(vertices[valid_to_all_vertex(v_id)].edge);
200 }
201 int leader_edge_of_edge(const int e_id) const
202 {
203 assert(adj_prepared);
204 return (edges[valid_to_all_edge(e_id)].leader < 0) ? -1 : all_to_valid_edge(edges[valid_to_all_edge(e_id)].leader);
205 }
206
207 // number of follower edges of a leader edge
208 int n_follower_edges(const int e_id) const
209 {
210 assert(adj_prepared);
211 return edges[valid_to_all_edge(e_id)].followers.size();
212 }
213 // number of elements have this edge
214 int n_face_neighbors(const int e_id) const { return edges[valid_to_all_edge(e_id)].n_elem(); }
215 // return the only element that has this edge
216 int face_neighbor(const int e_id) const { return all_to_valid_elem(edges[valid_to_all_edge(e_id)].get_element()); }
217
218 bool is_boundary_vertex(const int vertex_global_id) const override { return vertices[valid_to_all_vertex(vertex_global_id)].isboundary; }
219 bool is_boundary_edge(const int edge_global_id) const override { return edges[valid_to_all_edge(edge_global_id)].isboundary; }
220 bool is_boundary_element(const int element_global_id) const override;
221
222 void refine(const int n_refinement, const double t) override;
223
224 bool save(const std::string &path) const override
225 {
226 // TODO
227 return false;
228 }
229
230 bool build_from_matrices(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F) override;
231
232 void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector<std::vector<int>> &nodes) override;
233 RowVectorNd edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const override;
234 RowVectorNd face_node(const Navigation::Index &index, const int n_new_nodes, const int i, const int j) const override;
235
236 void normalize() override;
237
238 double edge_length(const int gid) const override;
239
240 void compute_elements_tag() override;
241 void update_elements_tag() override;
242
243 void set_point(const int global_index, const RowVectorNd &p) override;
244
245 RowVectorNd point(const int global_index) const override
246 {
247 assert(index_prepared);
248 return vertices[valid_to_all_vertex(global_index)].pos.transpose();
249 }
250 RowVectorNd edge_barycenter(const int index) const override;
251
252 void bounding_box(RowVectorNd &min, RowVectorNd &max) const override;
253
254 void compute_boundary_ids(const double eps) override;
255 void compute_boundary_ids(const std::function<int(const RowVectorNd &)> &marker) override;
256 void compute_boundary_ids(const std::function<int(const RowVectorNd &, bool)> &marker) override;
257 void compute_boundary_ids(const std::function<int(const size_t, const RowVectorNd &, bool)> &marker) override;
258 void compute_boundary_ids(const std::function<int(const std::vector<int> &, bool)> &marker) override;
259 void compute_body_ids(const std::function<int(const size_t, const RowVectorNd &)> &marker) override;
260 void compute_boundary_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &, bool)> &marker) override;
261
262 void set_boundary_ids(const std::vector<int> &boundary_ids) override;
263 void set_body_ids(const std::vector<int> &body_ids) override;
264
265 int get_boundary_id(const int primitive) const override { return edges[valid_to_all_edge(primitive)].boundary_id; };
266 int get_body_id(const int primitive) const override { return elements[valid_to_all_elem(primitive)].body_id; };
267
268 // Navigation wrapper
269 Navigation::Index get_index_from_face(int f, int lv = 0) const override;
270
271 // Navigation in a surface mesh
275
276 void triangulate_faces(Eigen::MatrixXi &tris, Eigen::MatrixXd &pts, std::vector<int> &ranges) const override;
277
278 // refine
279 void refine_element(int id_full);
280 void refine_elements(const std::vector<int> &ids);
281
282 // coarsen
283 void coarsen_element(int id_full);
284
285 // mark the true boundary vertices
286 void mark_boundary();
287
288 // map the barycentric coordinate in element to the weight on edge
289 static double element_weight_to_edge_weight(const int l, const Eigen::Vector2d &pos);
290
291 // call necessary functions before building bases
301
302 void build_index_mapping();
303
304 void append(const Mesh &mesh) override;
305
306 std::unique_ptr<Mesh> copy() const override;
307
308 private:
310 {
311 long operator()(const Eigen::Vector2i &a) const
312 {
313 return (long)((long)984120265 * a[0] + (long)125965121 * a[1]);
314 }
315 };
316
317 protected:
318 bool load(const std::string &path) override;
319 bool load(const GEO::Mesh &mesh) override;
320
321 // index map from vertices to valid ones, and its inverse
322 inline int all_to_valid_vertex(const int id) const
323 {
324 assert(index_prepared);
325 return all_to_valid_vertexMap[id];
326 };
327 inline int valid_to_all_vertex(const int id) const
328 {
329 assert(index_prepared);
330 return valid_to_all_vertexMap[id];
331 };
332
333 // index map from edges to valid ones, and its inverse
334 inline int all_to_valid_edge(const int id) const
335 {
336 assert(index_prepared);
337 assert(id < all_to_valid_edgeMap.size());
338 return all_to_valid_edgeMap[id];
339 };
340 inline int valid_to_all_edge(const int id) const
341 {
342 assert(index_prepared);
343 assert(id < valid_to_all_edgeMap.size());
344 return valid_to_all_edgeMap[id];
345 };
346
347 // index map from elements to valid ones, and its inverse
348 inline int all_to_valid_elem(const int id) const
349 {
350 assert(index_prepared);
351 return all_to_valid_elemMap[id];
352 };
353 inline int valid_to_all_elem(const int id) const
354 {
355 assert(index_prepared);
356 return valid_to_all_elemMap[id];
357 };
358
359 // find the mid-point of edge v[0]v[1], return -1 if not exists
360 int find_vertex(Eigen::Vector2i v) const;
361 int find_vertex(const int v1, const int v2) const { return find_vertex(Eigen::Vector2i(v1, v2)); };
362
363 // find the mid-point of edge v[0]v[1], create one if not exists
364 int get_vertex(Eigen::Vector2i v);
365
366 // find the edge v[0]v[1], return -1 if not exists
367 int find_edge(Eigen::Vector2i v) const;
368 int find_edge(const int v1, const int v2) const { return find_edge(Eigen::Vector2i(v1, v2)); };
369
370 // find the edge v[0]v[1], create one if not exists
371 int get_edge(Eigen::Vector2i v);
372 int get_edge(const int v1, const int v2) { return get_edge(Eigen::Vector2i(v1, v2)); };
373
374 // list all follower edges of a potential leader edge, returns nothing if it's a follower or conforming edge
375 void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector<follower_edge> &list) const;
376
377 // call traverse_edge() for every interface, and store everything needed
379
380 // assign ncElement2D.leader_edges and ncVertex2D.weight
382
383 // edges are created if not exist
384 // return the id of this new element
385 int add_element(Eigen::Vector3i v, int parent = -1);
386
387 int n_elements = 0;
388
389 bool index_prepared = false;
390 bool adj_prepared = false;
391
392 std::vector<ncElem> elements;
393 std::vector<ncVert> vertices;
394 std::vector<ncBoundary> edges;
395
396 std::unordered_map<Eigen::Vector2i, int, ArrayHasher2D> midpointMap;
397 std::unordered_map<Eigen::Vector2i, int, ArrayHasher2D> edgeMap;
398
402
403 std::vector<int> refineHistory;
404
405 // elementAdj(i, j) = 1 iff element i touches element j
406 Eigen::SparseMatrix<bool, Eigen::RowMajor> elementAdj;
407 };
408 } // namespace mesh
409} // namespace polyfem
int V
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:39
int all_to_valid_elem(const int id) const
Definition NCMesh2D.hpp:348
int find_edge(Eigen::Vector2i v) const
Definition NCMesh2D.cpp:125
bool is_boundary_element(const int element_global_id) const override
is cell boundary
Definition NCMesh2D.cpp:13
void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector< follower_edge > &list) const
Definition NCMesh2D.cpp:522
Navigation::Index switch_face(Navigation::Index idx) const override
Definition NCMesh2D.cpp:667
bool save(const std::string &path) const override
Definition NCMesh2D.hpp:224
std::vector< int > valid_to_all_edgeMap
Definition NCMesh2D.hpp:401
int n_face_neighbors(const int e_id) const
Definition NCMesh2D.hpp:214
NCMesh2D(NCMesh2D &&)=default
RowVectorNd point(const int global_index) const override
point coordinates
Definition NCMesh2D.hpp:245
Navigation::Index switch_vertex(Navigation::Index idx) const override
Definition NCMesh2D.cpp:620
int leader_edge_of_vertex(const int v_id) const
Definition NCMesh2D.hpp:196
std::unique_ptr< Mesh > copy() const override
Create a copy of the mesh.
Definition NCMesh2D.cpp:517
void attach_higher_order_nodes(const Eigen::MatrixXd &V, const std::vector< std::vector< int > > &nodes) override
attach high order nodes
Definition NCMesh2D.cpp:71
int face_edge(const int f_id, const int le_id) const
Definition NCMesh2D.hpp:195
void refine_elements(const std::vector< int > &ids)
Definition NCMesh2D.cpp:244
void prepare_mesh() override
method used to finalize the mesh.
Definition NCMesh2D.hpp:292
std::vector< ncVert > vertices
Definition NCMesh2D.hpp:393
std::vector< int > all_to_valid_elemMap
Definition NCMesh2D.hpp:399
bool is_conforming() const override
if the mesh is conforming
Definition NCMesh2D.hpp:166
static double element_weight_to_edge_weight(const int l, const Eigen::Vector2d &pos)
Definition NCMesh2D.cpp:427
int n_follower_edges(const int e_id) const
Definition NCMesh2D.hpp:208
void refine_element(int id_full)
Definition NCMesh2D.cpp:178
void set_boundary_ids(const std::vector< int > &boundary_ids) override
Set the boundary selection from a vector.
Definition NCMesh2D.cpp:790
int n_faces() const override
number of faces
Definition NCMesh2D.hpp:168
void set_point(const int global_index, const RowVectorNd &p) override
Set the point.
Definition NCMesh2D.cpp:712
int all_to_valid_vertex(const int id) const
Definition NCMesh2D.hpp:322
std::vector< ncElem > elements
Definition NCMesh2D.hpp:392
RowVectorNd face_node(const Navigation::Index &index, const int n_new_nodes, const int i, const int j) const override
Definition NCMesh2D.cpp:86
int find_vertex(const int v1, const int v2) const
Definition NCMesh2D.hpp:361
void set_body_ids(const std::vector< int > &body_ids) override
Set the volume sections.
Definition NCMesh2D.cpp:781
Navigation::Index switch_edge(Navigation::Index idx) const override
Definition NCMesh2D.cpp:644
int get_edge(Eigen::Vector2i v)
Definition NCMesh2D.cpp:135
int add_element(Eigen::Vector3i v, int parent=-1)
Definition NCMesh2D.cpp:148
void coarsen_element(int id_full)
Definition NCMesh2D.cpp:254
int get_vertex(Eigen::Vector2i v)
Definition NCMesh2D.cpp:111
Navigation::Index get_index_from_face(int f, int lv=0) const override
Definition NCMesh2D.cpp:607
double edge_length(const int gid) const override
edge length
Definition NCMesh2D.cpp:695
int get_boundary_id(const int primitive) const override
Get the boundary selection of an element (face in 3d, edge in 2d)
Definition NCMesh2D.hpp:265
int valid_to_all_edge(const int id) const
Definition NCMesh2D.hpp:340
int n_vertices() const override
number of vertices
Definition NCMesh2D.hpp:177
bool is_boundary_edge(const int edge_global_id) const override
is edge boundary
Definition NCMesh2D.hpp:219
int get_body_id(const int primitive) const override
Get the volume selection of an element (cell in 3d, face in 2d)
Definition NCMesh2D.hpp:266
void refine(const int n_refinement, const double t) override
refine the mesh
Definition NCMesh2D.cpp:23
void normalize() override
normalize the mesh
Definition NCMesh2D.cpp:683
std::vector< int > refineHistory
Definition NCMesh2D.hpp:403
int valid_to_all_elem(const int id) const
Definition NCMesh2D.hpp:353
std::vector< int > valid_to_all_elemMap
Definition NCMesh2D.hpp:399
int edge_vertex(const int e_id, const int lv_id) const override
id of the edge vertex
Definition NCMesh2D.hpp:192
int leader_edge_of_edge(const int e_id) const
Definition NCMesh2D.hpp:201
std::vector< int > all_to_valid_edgeMap
Definition NCMesh2D.hpp:401
std::vector< int > all_to_valid_vertexMap
Definition NCMesh2D.hpp:400
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > midpointMap
Definition NCMesh2D.hpp:396
std::vector< ncBoundary > edges
Definition NCMesh2D.hpp:394
RowVectorNd edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const override
Definition NCMesh2D.cpp:77
void compute_boundary_ids(const double eps) override
computes the selection based on the bbx of the mesh.
Definition NCMesh2D.cpp:812
bool build_from_matrices(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F) override
build a mesh from matrices
Definition NCMesh2D.cpp:39
int find_edge(const int v1, const int v2) const
Definition NCMesh2D.hpp:368
void compute_elements_tag() override
compute element types, see ElementType
Definition NCMesh2D.cpp:703
int face_vertex(const int f_id, const int lv_id) const override
id of the face vertex
Definition NCMesh2D.hpp:191
RowVectorNd edge_barycenter(const int index) const override
edge barycenter
Definition NCMesh2D.cpp:717
void triangulate_faces(Eigen::MatrixXi &tris, Eigen::MatrixXd &pts, std::vector< int > &ranges) const override
generate a triangular representation of every face
Definition NCMesh2D.cpp:725
int all_to_valid_edge(const int id) const
Definition NCMesh2D.hpp:334
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > edgeMap
Definition NCMesh2D.hpp:397
int find_vertex(Eigen::Vector2i v) const
Definition NCMesh2D.cpp:101
void bounding_box(RowVectorNd &min, RowVectorNd &max) const override
computes the bbox of the mesh
Definition NCMesh2D.cpp:590
int cell_vertex(const int f_id, const int lv_id) const override
id of the vertex of a cell
Definition NCMesh2D.hpp:193
int face_ref_level(const int f_id) const
Definition NCMesh2D.hpp:189
void compute_body_ids(const std::function< int(const size_t, const RowVectorNd &)> &marker) override
computes boundary selections based on a function
Definition NCMesh2D.cpp:799
int n_face_vertices(const int f_id) const override
number of vertices of a face
Definition NCMesh2D.hpp:187
int valid_to_all_vertex(const int id) const
Definition NCMesh2D.hpp:327
virtual ~NCMesh2D()=default
void build_element_vertex_adjacency()
Definition NCMesh2D.cpp:375
int n_edges() const override
number of edges
Definition NCMesh2D.hpp:169
NCMesh2D & operator=(const NCMesh2D &)=default
int get_edge(const int v1, const int v2)
Definition NCMesh2D.hpp:372
NCMesh2D & operator=(NCMesh2D &&)=default
int face_neighbor(const int e_id) const
Definition NCMesh2D.hpp:216
bool is_boundary_vertex(const int vertex_global_id) const override
is vertex boundary
Definition NCMesh2D.hpp:218
Eigen::SparseMatrix< bool, Eigen::RowMajor > elementAdj
Definition NCMesh2D.hpp:406
NCMesh2D(const NCMesh2D &)=default
std::vector< int > valid_to_all_vertexMap
Definition NCMesh2D.hpp:400
bool load(const std::string &path) override
loads a mesh from the path
Definition NCMesh2D.cpp:548
void update_elements_tag() override
Update elements types.
Definition NCMesh2D.cpp:707
void append(const Mesh &mesh) override
appends a new mesh to the end of this
Definition NCMesh2D.cpp:492
Eigen::Matrix< double, 1, Eigen::Dynamic, Eigen::RowMajor, 1, 3 > RowVectorNd
Definition Types.hpp:11
long operator()(const Eigen::Vector2i &a) const
Definition NCMesh2D.hpp:311
follower_edge(int id_, double p1_, double p2_)
Definition NCMesh2D.hpp:17
follower_face(int id_, Eigen::Vector2d p1_, Eigen::Vector2d p2_, Eigen::Vector2d p3_)
Definition NCMesh2D.hpp:30
int find_opposite_element(int e) const
Definition NCMesh2D.hpp:86
ncBoundary(const Eigen::VectorXi vert)
Definition NCMesh2D.hpp:57
ncElem(const int dim_, const Eigen::VectorXi vertices_, const int level_, const int parent_)
Definition NCMesh2D.hpp:121
ncVert(const Eigen::VectorXd pos_)
Definition NCMesh2D.hpp:41