Wildmeshing Toolkit
EdgeMesh.cpp
Go to the documentation of this file.
1 #include "EdgeMesh.hpp"
2 
3 
5 #include <numeric>
6 #include <wmtk/utils/Logger.hpp>
7 namespace wmtk {
8  EdgeMesh::~EdgeMesh() = default;
10  : MeshCRTP<EdgeMesh>(1)
11  , m_ve_handle(register_attribute_typed<int64_t>("m_ve", PrimitiveType::Vertex, 1, false, -1))
12  , m_ev_handle(register_attribute_typed<int64_t>("m_ev", PrimitiveType::Edge, 2, false, -1))
13  , m_ee_handle(register_attribute_typed<int64_t>("m_ee", PrimitiveType::Edge, 2, false, -1))
14 {}
15 
16 
17 bool EdgeMesh::is_boundary(PrimitiveType pt, const Tuple& tuple) const
18 {
19  switch (pt) {
20  case PrimitiveType::Vertex: return is_boundary_vertex(tuple);
24  default: break;
25  }
26  assert(
27  false); // "tried to compute the boundary of an edge mesh for an invalid simplex dimension"
28  return false;
29 }
30 
31 bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const
32 {
33  assert(is_valid(tuple));
34  const attribute::Accessor<int64_t> ee_accessor = create_const_accessor<int64_t>(m_ee_handle);
35  return ee_accessor.const_vector_attribute<2>(tuple)(tuple.m_local_vid) < 0;
36 }
37 
39 {
40  assert(is_valid(tuple));
41  bool ccw = is_ccw(tuple);
42 
43  switch (type) {
45  return Tuple(
46  1 - tuple.m_local_vid,
47  tuple.m_local_eid,
48  tuple.m_local_fid,
49  tuple.m_global_cid);
50  case PrimitiveType::Edge: {
51  const int64_t gvid = id(tuple, PrimitiveType::Vertex);
52 
53  const attribute::Accessor<int64_t> ee_accessor =
54  create_const_accessor<int64_t>(m_ee_handle);
55  auto ee = ee_accessor.const_vector_attribute<2>(tuple);
56 
57  int64_t gcid_new = ee(tuple.m_local_vid);
58 
59  // This is for special case self-loop, just to make sure the local vid of the returned
60  // tuple is the same as the input. (When doing double-switch this is needed)
61  if (gcid_new == tuple.m_global_cid) {
62  return tuple;
63  }
64 
65  int64_t lvid_new = -1;
66 
67  const attribute::Accessor<int64_t> ev_accessor =
68  create_const_accessor<int64_t>(m_ev_handle);
69  auto ev = ev_accessor.index_access().const_vector_attribute<2>(gcid_new);
70 
71  for (int64_t i = 0; i < 2; ++i) {
72  if (ev(i) == gvid) {
73  lvid_new = i;
74  // break;
75  }
76  }
77  assert(lvid_new != -1);
78 
79 
80  const Tuple res(lvid_new, tuple.m_local_eid, tuple.m_local_fid, gcid_new);
81  assert(is_valid(res));
82  return res;
83  }
86  default: assert(false); // "Tuple switch: Invalid primitive type"
87  }
88 
89  return Tuple();
90 }
91 
92 bool EdgeMesh::is_ccw(const Tuple& tuple) const
93 {
94  assert(is_valid(tuple));
95  return tuple.m_local_vid == 0;
96 }
97 
99  Eigen::Ref<const RowVectors2l> EV,
100  Eigen::Ref<const RowVectors2l> EE,
101  Eigen::Ref<const VectorXl> VE)
102 {
103  // reserve memory for attributes
104 
105  std::vector<int64_t> cap{static_cast<int64_t>(VE.rows()), static_cast<int64_t>(EE.rows())};
106 
107  set_capacities(cap);
108 
109  // get accessors for topology
110  attribute::Accessor<int64_t> ev_accessor = create_accessor<int64_t>(m_ev_handle);
111  attribute::Accessor<int64_t> ee_accessor = create_accessor<int64_t>(m_ee_handle);
112  attribute::Accessor<int64_t> ve_accessor = create_accessor<int64_t>(m_ve_handle);
113 
116 
117  // iterate over the matrices and fill attributes
118 
119  for (int64_t i = 0; i < capacity(PrimitiveType::Edge); ++i) {
120  ev_accessor.index_access().vector_attribute<2>(i) = EV.row(i).transpose();
121  ee_accessor.index_access().vector_attribute<2>(i) = EE.row(i).transpose();
122 
123  e_flag_accessor.index_access().scalar_attribute(i) |= 0x1;
124  }
125  // m_ve
126  for (int64_t i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
127  ve_accessor.index_access().scalar_attribute(i) = VE(i);
128  v_flag_accessor.index_access().scalar_attribute(i) |= 0x1;
129  }
130 }
131 
132 void EdgeMesh::initialize(Eigen::Ref<const RowVectors2l> E, bool is_free)
133 {
134  this->m_is_free = is_free;
135  auto [EE, VE] = edgemesh_topology_initialization(E);
136  if (is_free) {
137  EE.setConstant(-1);
138  }
139  initialize(E, EE, VE);
140 }
141 void EdgeMesh::initialize_free(int64_t count)
142 {
143  RowVectors2l S(count, 2);
144  std::iota(S.data(), S.data() + S.size(), int64_t(0));
145  initialize(S, true);
146 }
147 
148 Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const int64_t gid) const
149 {
150  switch (type) {
151  case PrimitiveType::Vertex: {
152  return vertex_tuple_from_id(gid);
153  }
154  case PrimitiveType::Edge: {
155  return edge_tuple_from_id(gid);
156  }
158  throw std::runtime_error("no tet tuple supported for edgemesh");
159  break;
160  }
162  throw std::runtime_error("no tet tuple supported for edgemesh");
163  break;
164  }
165  default: assert(false); //"Invalid primitive type"
166  }
167 
168  return Tuple();
169 }
170 
172 {
173  const attribute::Accessor<int64_t> ve_accessor = create_const_accessor<int64_t>(m_ve_handle);
174  auto e = ve_accessor.index_access().const_scalar_attribute(id);
175  const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
176  auto ev = ev_accessor.index_access().const_vector_attribute<2>(e);
177  for (int64_t i = 0; i < 2; ++i) {
178  if (ev(i) == id) {
179  Tuple v_tuple = Tuple(i, -1, -1, e);
180  return v_tuple;
181  }
182  }
183  assert(false); // "vertex_tuple_from_id failed"
184 
185  return Tuple();
186 }
187 
189 {
190  Tuple e_tuple = Tuple(0, -1, -1, id);
191 
192  assert(is_valid(e_tuple));
193  return e_tuple;
194 }
195 
196 Tuple EdgeMesh::tuple_from_global_ids(int64_t eid, int64_t vid) const
197 {
198  const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
199  auto ev = ev_accessor.index_access().const_vector_attribute<2>(eid);
200 
201  int64_t lvid = -1;
202 
203  for (int j = 0; j < 2; ++j) {
204  if (ev(j) == vid) {
205  lvid = j;
206  }
207  }
208  assert(lvid != -1);
209 
210  return Tuple(lvid, -1, -1, eid);
211 }
212 
213 
214 bool EdgeMesh::is_valid(const Tuple& tuple) const
215 {
216  if (!Mesh::is_valid(tuple)) {
217  return false;
218  }
219 
220  const bool is_connectivity_valid = tuple.m_local_vid >= 0 && tuple.m_global_cid >= 0;
221  if (!is_connectivity_valid) {
222 #if !defined(NDEBUG)
223  logger().debug(
224  "tuple.m_local_vid={} >= 0"
225  " tuple.m_global_cid={} >= 0",
226  tuple.m_local_vid,
227  tuple.m_global_cid);
228  assert(tuple.m_local_vid >= 0);
229  assert(tuple.m_global_cid >= 0);
230 #endif
231  return false;
232  }
233  return true;
234 }
235 
237 {
238  // get accessors for topology
239  const attribute::Accessor<int64_t> ev_accessor = create_const_accessor<int64_t>(m_ev_handle);
240  const attribute::Accessor<int64_t> ee_accessor = create_const_accessor<int64_t>(m_ee_handle);
241  const attribute::Accessor<int64_t> ve_accessor = create_const_accessor<int64_t>(m_ve_handle);
244 
245  // VE and EV
246  for (int64_t i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
247  if (v_flag_accessor.index_access().const_scalar_attribute(i) == 0) {
248  wmtk::logger().debug("Vertex {} is deleted", i);
249  continue;
250  }
251  int cnt = 0;
252  for (int64_t j = 0; j < 2; ++j) {
253  if (ev_accessor.index_access().const_vector_attribute<2>(
254  ve_accessor.index_access().const_scalar_attribute(i))[j] == i) {
255  cnt++;
256  }
257  }
258  if (cnt == 0) {
259  return false;
260  }
261  }
262 
263  // EV and EE
264  for (int64_t i = 0; i < capacity(PrimitiveType::Edge); ++i) {
265  if (e_flag_accessor.index_access().const_scalar_attribute(i) == 0) {
266  wmtk::logger().debug("Edge {} is deleted", i);
267  continue;
268  }
269  // TODO: need to handle cornor case (self-loop)
270  }
271 
272  return true;
273 }
274 
275 std::vector<std::vector<TypedAttributeHandle<int64_t>>> EdgeMesh::connectivity_attributes() const
276 {
277  std::vector<std::vector<TypedAttributeHandle<int64_t>>> handles(2);
278 
279  handles[1].push_back(m_ve_handle);
280  handles[1].push_back(m_ee_handle);
281  handles[0].push_back(m_ev_handle);
282 
283  return handles;
284 }
285 
286 std::vector<Tuple> EdgeMesh::orient_vertices(const Tuple& tuple) const
287 {
288  int64_t cid = tuple.m_global_cid;
289  return {Tuple(0, -1, -1, cid), Tuple(1, -1, -1, cid)};
290 }
291 
292 
293 } // namespace wmtk
attribute::TypedAttributeHandle< int64_t > m_ee_handle
Definition: EdgeMesh.hpp:81
Tuple tuple_from_global_ids(int64_t eid, int64_t vid) const
Definition: EdgeMesh.cpp:196
bool is_connectivity_valid() const override
Definition: EdgeMesh.cpp:236
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const override
switch the orientation of the Tuple of the given dimension
Definition: EdgeMesh.cpp:38
bool is_boundary_vertex(const Tuple &tuple) const
Definition: EdgeMesh.cpp:31
bool is_boundary(const simplex::Simplex &tuple) const
check if a simplex lies on a boundary or not
Definition: Mesh.cpp:106
void initialize_free(int64_t count)
Definition: EdgeMesh.cpp:141
Tuple tuple_from_id(const PrimitiveType type, const int64_t gid) const override
internal function that returns the tuple of requested type, and has the global index cid
Definition: EdgeMesh.cpp:148
Tuple edge_tuple_from_id(int64_t id) const
Definition: EdgeMesh.cpp:188
std::vector< Tuple > orient_vertices(const Tuple &tuple) const override
Definition: EdgeMesh.cpp:286
attribute::TypedAttributeHandle< int64_t > m_ev_handle
Definition: EdgeMesh.hpp:80
Tuple vertex_tuple_from_id(int64_t id) const
Definition: EdgeMesh.cpp:171
bool is_ccw(const Tuple &tuple) const override
TODO this needs dimension?
Definition: EdgeMesh.cpp:92
attribute::TypedAttributeHandle< int64_t > m_ve_handle
Definition: EdgeMesh.hpp:78
~EdgeMesh() override
void initialize(Eigen::Ref< const RowVectors2l > E, bool is_free=false)
Definition: EdgeMesh.cpp:132
bool is_valid(const Tuple &tuple) const final override
check validity of tuple including its hash
Definition: EdgeMesh.cpp:214
std::vector< std::vector< TypedAttributeHandle< int64_t > > > connectivity_attributes() const override
Returns a vector of vectors of attribute handles.
Definition: EdgeMesh.cpp:275
A Curiously Recurring Template Pattern shim to enable generic specialization of functions.
Definition: MeshCRTP.hpp:24
int64_t id(const Tuple &tuple, PrimitiveType type) const
return the global id of the Tuple of the given dimension
Definition: Mesh.hpp:1020
bool m_is_free
Definition: Mesh.hpp:846
void set_capacities(std::vector< int64_t > capacities)
int64_t capacity(PrimitiveType type) const
read in the m_capacities return the upper bound for the number of entities of the given dimension
bool is_free() const
Definition: Mesh.hpp:987
virtual bool is_valid(const Tuple &tuple) const
check validity of tuple including its hash
Definition: Mesh.cpp:112
const attribute::Accessor< char > get_flag_accessor(PrimitiveType type) const
Definition: Mesh.cpp:158
int8_t m_local_vid
Definition: Tuple.hpp:47
int8_t m_local_eid
Definition: Tuple.hpp:48
int64_t m_global_cid
Definition: Tuple.hpp:46
int8_t m_local_fid
Definition: Tuple.hpp:49
CachingBaseType & index_access()
Definition: Accessor.hpp:95
ConstMapResult< D > const_vector_attribute(const ArgType &t) const
T const_scalar_attribute(const int64_t index) const
MapResult< D > vector_attribute(const int64_t index)
T & scalar_attribute(const int64_t index)
ConstMapResult< D > const_vector_attribute(const int64_t index) const
Definition: Accessor.hpp:6
spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:58
RowVectors< int64_t, 2 > RowVectors2l
Definition: Types.hpp:46
std::tuple< RowVectors2l, VectorXl > edgemesh_topology_initialization(Eigen::Ref< const RowVectors2l > E)