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_) {};
42 ~ncVert() {};
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 std::pair<RowVectorNd, int> edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const override;
234 std::pair<RowVectorNd, int> 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 std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &, bool)> &marker) override;
255
256 void compute_body_ids(const std::function<int(const size_t, const std::vector<int> &, const RowVectorNd &)> &marker) override;
257
258 void set_boundary_ids(const std::vector<int> &boundary_ids) override;
259 void set_body_ids(const std::vector<int> &body_ids) override;
260
261 int get_boundary_id(const int primitive) const override { return edges[valid_to_all_edge(primitive)].boundary_id; };
262 int get_body_id(const int primitive) const override { return elements[valid_to_all_elem(primitive)].body_id; };
263
264 // Navigation wrapper
265 Navigation::Index get_index_from_face(int f, int lv = 0) const override;
266
267 // Navigation in a surface mesh
271
272 // void triangulate_faces(Eigen::MatrixXi &tris, Eigen::MatrixXd &pts, std::vector<int> &ranges) const override;
273
274 // refine
275 void refine_element(int id_full);
276 void refine_elements(const std::vector<int> &ids);
277
278 // coarsen
279 void coarsen_element(int id_full);
280
281 // mark the true boundary vertices
282 void mark_boundary();
283
284 // map the barycentric coordinate in element to the weight on edge
285 static double element_weight_to_edge_weight(const int l, const Eigen::Vector2d &pos);
286
287 // call necessary functions before building bases
297
298 void build_index_mapping();
299
300 void append(const Mesh &mesh) override;
301
302 std::unique_ptr<Mesh> copy() const override;
303
304 private:
306 {
307 long operator()(const Eigen::Vector2i &a) const
308 {
309 return (long)((long)984120265 * a[0] + (long)125965121 * a[1]);
310 }
311 };
312
313 protected:
314 bool load(const std::string &path) override;
315 bool load(const GEO::Mesh &mesh) override;
316
317 // index map from vertices to valid ones, and its inverse
318 inline int all_to_valid_vertex(const int id) const
319 {
320 assert(index_prepared);
321 return all_to_valid_vertexMap[id];
322 };
323 inline int valid_to_all_vertex(const int id) const
324 {
325 assert(index_prepared);
326 return valid_to_all_vertexMap[id];
327 };
328
329 // index map from edges to valid ones, and its inverse
330 inline int all_to_valid_edge(const int id) const
331 {
332 assert(index_prepared);
333 assert(id < all_to_valid_edgeMap.size());
334 return all_to_valid_edgeMap[id];
335 };
336 inline int valid_to_all_edge(const int id) const
337 {
338 assert(index_prepared);
339 assert(id < valid_to_all_edgeMap.size());
340 return valid_to_all_edgeMap[id];
341 };
342
343 // index map from elements to valid ones, and its inverse
344 inline int all_to_valid_elem(const int id) const
345 {
346 assert(index_prepared);
347 return all_to_valid_elemMap[id];
348 };
349 inline int valid_to_all_elem(const int id) const
350 {
351 assert(index_prepared);
352 return valid_to_all_elemMap[id];
353 };
354
355 // find the mid-point of edge v[0]v[1], return -1 if not exists
356 int find_vertex(Eigen::Vector2i v) const;
357 int find_vertex(const int v1, const int v2) const { return find_vertex(Eigen::Vector2i(v1, v2)); };
358
359 // find the mid-point of edge v[0]v[1], create one if not exists
360 int get_vertex(Eigen::Vector2i v);
361
362 // find the edge v[0]v[1], return -1 if not exists
363 int find_edge(Eigen::Vector2i v) const;
364 int find_edge(const int v1, const int v2) const { return find_edge(Eigen::Vector2i(v1, v2)); };
365
366 // find the edge v[0]v[1], create one if not exists
367 int get_edge(Eigen::Vector2i v);
368 int get_edge(const int v1, const int v2) { return get_edge(Eigen::Vector2i(v1, v2)); };
369
370 // list all follower edges of a potential leader edge, returns nothing if it's a follower or conforming edge
371 void traverse_edge(Eigen::Vector2i v, double p1, double p2, int depth, std::vector<follower_edge> &list) const;
372
373 // call traverse_edge() for every interface, and store everything needed
375
376 // assign ncElement2D.leader_edges and ncVertex2D.weight
378
379 // edges are created if not exist
380 // return the id of this new element
381 int add_element(Eigen::Vector3i v, int parent = -1);
382
383 int n_elements = 0;
384
385 bool index_prepared = false;
386 bool adj_prepared = false;
387
388 std::vector<ncElem> elements;
389 std::vector<ncVert> vertices;
390 std::vector<ncBoundary> edges;
391
392 std::unordered_map<Eigen::Vector2i, int, ArrayHasher2D> midpointMap;
393 std::unordered_map<Eigen::Vector2i, int, ArrayHasher2D> edgeMap;
394
398
399 std::vector<int> refineHistory;
400
401 // elementAdj(i, j) = 1 iff element i touches element j
402 Eigen::SparseMatrix<bool, Eigen::RowMajor> elementAdj;
403 };
404 } // namespace mesh
405} // 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:344
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
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 NCMesh2D.cpp:800
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:397
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:288
std::vector< ncVert > vertices
Definition NCMesh2D.hpp:389
std::vector< int > all_to_valid_elemMap
Definition NCMesh2D.hpp:395
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:791
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:318
std::vector< ncElem > elements
Definition NCMesh2D.hpp:388
int find_vertex(const int v1, const int v2) const
Definition NCMesh2D.hpp:357
void set_body_ids(const std::vector< int > &body_ids) override
Set the volume sections.
Definition NCMesh2D.cpp:782
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:261
int valid_to_all_edge(const int id) const
Definition NCMesh2D.hpp:336
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:262
void refine(const int n_refinement, const double t) override
refine the mesh
Definition NCMesh2D.cpp:23
std::pair< RowVectorNd, int > face_node(const Navigation::Index &index, const int n_new_nodes, const int i, const int j) const override
Definition NCMesh2D.cpp:86
void normalize() override
normalize the mesh
Definition NCMesh2D.cpp:683
std::vector< int > refineHistory
Definition NCMesh2D.hpp:399
int valid_to_all_elem(const int id) const
Definition NCMesh2D.hpp:349
std::vector< int > valid_to_all_elemMap
Definition NCMesh2D.hpp:395
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:397
std::vector< int > all_to_valid_vertexMap
Definition NCMesh2D.hpp:396
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > midpointMap
Definition NCMesh2D.hpp:392
std::vector< ncBoundary > edges
Definition NCMesh2D.hpp:390
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:364
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
int all_to_valid_edge(const int id) const
Definition NCMesh2D.hpp:330
std::unordered_map< Eigen::Vector2i, int, ArrayHasher2D > edgeMap
Definition NCMesh2D.hpp:393
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
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:323
virtual ~NCMesh2D()=default
void build_element_vertex_adjacency()
Definition NCMesh2D.cpp:375
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 NCMesh2D.cpp:813
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:368
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:402
NCMesh2D(const NCMesh2D &)=default
std::vector< int > valid_to_all_vertexMap
Definition NCMesh2D.hpp:396
bool load(const std::string &path) override
loads a mesh from the path
Definition NCMesh2D.cpp:548
std::pair< RowVectorNd, int > edge_node(const Navigation::Index &index, const int n_new_nodes, const int i) const override
Definition NCMesh2D.cpp:77
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:13
long operator()(const Eigen::Vector2i &a) const
Definition NCMesh2D.hpp:307
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