Wildmeshing Toolkit
UpdateEdgeOperationMultiMeshMapFunctor.cpp
Go to the documentation of this file.
2 
3 #include <wmtk/EdgeMesh.hpp>
4 #include <wmtk/Mesh.hpp>
5 #include <wmtk/PointMesh.hpp>
6 #include <wmtk/TetMesh.hpp>
7 #include <wmtk/TriMesh.hpp>
11 
12 #include <wmtk/utils/Logger.hpp>
13 
14 
15 namespace wmtk::operations::utils {
16 
17 namespace {
18 constexpr static PrimitiveType PV = PrimitiveType::Vertex;
19 constexpr static PrimitiveType PE = PrimitiveType::Edge;
20 constexpr static PrimitiveType PF = PrimitiveType::Triangle;
22 } // namespace
24  Mesh& m,
25  const std::vector<std::vector<std::tuple<int64_t, std::vector<Tuple>>>>& simplices_to_update,
26  const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps) const
27 {
28  // assert(m.top_cell_dimension() + 1 == simplices_to_update.size());
29  constexpr static PrimitiveType PTs[] = {PV, PE, PF, PT};
30  // logger().trace("{} {}", m.top_cell_dimension(), simplices_to_update.size());
31  for (size_t j = 0; j < simplices_to_update.size(); ++j) {
33  .update_map_tuple_hashes(m, PTs[j], simplices_to_update[j], split_cell_maps);
34  }
35 }
36 
37 
39  TriMesh& m,
40  const tri_mesh::EdgeOperationData& fmoe) const
41 {
42  const auto& parent_incident_datas = fmoe.incident_face_datas();
43  auto& parent_mmmanager = m.m_multi_mesh_manager;
44  const auto& parent_incident_vids = fmoe.incident_vids();
45 
46  for (const auto& parent_data : parent_incident_datas) {
47  // std::cout << parent_data.fid << " has been processed" << std::endl;
48 
49  for (auto child_ptr : m.get_child_meshes()) {
50  // no ear replcaement required for free child meshes
51  if (child_ptr->is_free()) {
52  continue;
53  }
54  if (child_ptr->top_cell_dimension() != 1) {
55  continue; // only deal with child edgemeshes
56  }
57 
58  const auto& child_mmmanager = child_ptr->m_multi_mesh_manager;
59  int64_t child_id = child_mmmanager.child_id();
60  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
61  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
62  auto child_to_parent_accessor = child_ptr->create_accessor(child_to_parent_handle);
63  auto parent_to_child_accessor = m.create_accessor(parent_to_child_handle);
64  auto child_cell_flag_accessor = child_ptr->get_const_flag_accessor(PrimitiveType::Edge);
65 
66  std::vector<std::pair<Tuple, Tuple>> update_pairs;
67 
68  for (int ear_index = 0; ear_index < 2; ++ear_index) {
69  const int64_t parent_ear_eid_old = parent_data.ears[ear_index].eid;
70  const int64_t parent_merged_eid = parent_data.new_edge_id;
71  const int64_t parent_new_fid = parent_data.merged_edge_fid;
72 
73 
74  assert(parent_merged_eid != -1);
75  assert(parent_new_fid != -1);
76 
77  auto parent_to_child_data = Mesh::get_index_access(parent_to_child_accessor)
78  .const_vector_attribute(parent_ear_eid_old);
79 
80  Tuple parent_tuple, child_tuple;
81  std::tie(parent_tuple, child_tuple) =
82  wmtk::multimesh::utils::vectors_to_tuples(parent_to_child_data);
83 
84  if (child_tuple.is_null()) {
85  // not child_tuple on this parent edge
86  continue;
87  }
88 
89 
90  // check also the flag accessor of child mesh
91  const bool child_tuple_exists = child_cell_flag_accessor.is_active(child_tuple);
92  if (!child_tuple_exists) {
93  continue;
94  }
95 
96  const int64_t parent_old_vid =
97  m.parent_scope([&]() { return m.id_vertex(parent_tuple); });
98 
99 
100  int64_t parent_new_vid = -1;
101 
102  if (parent_ear_eid_old != parent_merged_eid) {
103  // other side
104  if (parent_old_vid == parent_incident_vids[0]) {
105  parent_new_vid = parent_incident_vids[1];
106  } else {
107  parent_new_vid = parent_old_vid;
108  }
109  } else {
110  // same side
111  parent_new_vid = parent_old_vid;
112  }
113 
114  assert(parent_new_vid != -1);
115 
116  Tuple new_parent_tuple =
117  m.tuple_from_global_ids(parent_new_fid, parent_merged_eid, parent_new_vid);
118 
119  update_pairs.push_back(std::make_pair(new_parent_tuple, child_tuple));
120  }
121 
122  for (const auto& pair : update_pairs) {
124  parent_to_child_accessor,
125  child_to_parent_accessor,
126  pair.first,
127  pair.second);
128  }
129  }
130  }
131 }
132 
134  TetMesh& m,
135  const tet_mesh::EdgeOperationData& tmoe) const
136 {
137  const auto& parent_incident_tet_datas = tmoe.incident_tet_datas();
138  const auto& parent_incident_face_datas = tmoe.incident_face_datas();
139  auto parent_mmmanager = m.m_multi_mesh_manager;
140 
141  for (const auto& parent_data : parent_incident_tet_datas) {
142  for (auto child_ptr : m.get_child_meshes()) {
143  // no ear replcaement required for free child meshes
144  if (child_ptr->is_free()) {
145  continue;
146  }
147  if (child_ptr->top_cell_dimension() == 2) {
148  // handle with child tri mesh
149  // update merge faces here
150  const auto& child_mmmanager = child_ptr->m_multi_mesh_manager;
151  const int64_t child_id = child_mmmanager.child_id();
152  const auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
153  const auto parent_to_child_handle =
154  parent_mmmanager.children().at(child_id).map_handle;
155  auto child_to_parent_accessor = child_ptr->create_accessor(child_to_parent_handle);
156  auto parent_to_child_accessor = m.create_accessor(parent_to_child_handle);
157  auto child_cell_flag_accessor =
158  child_ptr->get_const_flag_accessor(PrimitiveType::Triangle);
159 
160  std::vector<std::pair<Tuple, Tuple>> update_pairs;
161 
162  for (int ear_index = 0; ear_index < 2; ++ear_index) {
163  const int64_t parent_ear_fid_old = parent_data.ears[ear_index].fid;
164  const int64_t parent_merged_fid = parent_data.new_face_id;
165  const int64_t parent_new_tid =
166  parent_data.merged_face_tid; // can be move to outer loop
167 
168  assert(parent_merged_fid != -1);
169  assert(parent_new_tid != -1);
170 
171  auto parent_to_child_data = Mesh::get_index_access(parent_to_child_accessor)
172  .const_vector_attribute(parent_ear_fid_old);
173 
174  // TUPLE_SIZE is the number of tuples in terms of lon
175  Tuple parent_tuple, child_tuple;
176  std::tie(parent_tuple, child_tuple) =
177  wmtk::multimesh::utils::vectors_to_tuples(parent_to_child_data);
178 
179  if (child_tuple.is_null()) {
180  // not child_tuple on this parent face
181  continue;
182  }
183 
184 
185  bool child_tuple_exists = child_cell_flag_accessor.is_active(child_tuple);
186  if (!child_tuple_exists) {
187  continue;
188  }
189 
190  const int64_t parent_old_eid =
191  m.parent_scope([&]() { return m.id_edge(parent_tuple); });
192  const int64_t parent_old_vid =
193  m.parent_scope([&]() { return m.id_vertex(parent_tuple); });
194 
195 
196  // get the corresponding new eid and vid of parent
197  int64_t parent_new_eid = -1;
198  int64_t parent_new_vid = -1;
199 
200  if (parent_ear_fid_old != parent_merged_fid) {
201  // other side
202  if (parent_old_eid == parent_data.e02) {
203  parent_new_eid = parent_data.e12;
204  } else if (parent_old_eid == parent_data.e03) {
205  parent_new_eid = parent_data.e13;
206  } else if (parent_old_eid == parent_data.e23) {
207  parent_new_eid = parent_data.e23;
208  }
209 
210  if (parent_old_vid == parent_data.v0) {
211  parent_new_vid = parent_data.v1;
212  } else if (parent_old_vid == parent_data.v2) {
213  parent_new_vid = parent_data.v2;
214  } else if (parent_old_vid == parent_data.v3) {
215  parent_new_vid = parent_data.v3;
216  }
217  } else {
218  // same side
219  parent_new_eid = parent_old_eid;
220  parent_new_vid = parent_old_vid;
221  }
222 
223  assert(parent_new_eid != -1);
224  assert(parent_new_vid != -1);
225 
226  Tuple new_parent_tuple = m.tuple_from_global_ids(
227  parent_new_tid,
228  parent_merged_fid,
229  parent_new_eid,
230  parent_new_vid);
231 
232  update_pairs.push_back(std::make_pair(new_parent_tuple, child_tuple));
233  }
234 
235  for (const auto& pair : update_pairs) {
237  parent_to_child_accessor,
238  child_to_parent_accessor,
239  pair.first,
240  pair.second);
241  }
242 
243  } else if (child_ptr->top_cell_dimension() == 1) {
244  // handle with child edge mesh
245  // update merge edges here
246  // there are three ear edges per side
247  const auto& child_mmmanager = child_ptr->m_multi_mesh_manager;
248  int64_t child_id = child_mmmanager.child_id();
249  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
250  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
251  auto child_to_parent_accessor = child_ptr->create_accessor(child_to_parent_handle);
252  auto parent_to_child_accessor = m.create_accessor(parent_to_child_handle);
253  auto child_cell_flag_accessor =
254  child_ptr->get_const_flag_accessor(PrimitiveType::Edge);
255 
256  std::vector<std::pair<Tuple, Tuple>> update_pairs;
257 
258  for (int ear_index = 0; ear_index < 2; ++ear_index) {
259  const int64_t parent_ear_fid_old = parent_data.ears[ear_index].fid;
260  const int64_t parent_merged_fid = parent_data.new_face_id;
261  const int64_t parent_new_tid = parent_data.merged_face_tid;
262 
263 
264  std::array<int64_t, 3> parent_old_eids;
265  std::array<int64_t, 3> parent_new_eids = {
266  {parent_data.e12, parent_data.e13, parent_data.e23}};
267 
268  if (parent_ear_fid_old != parent_merged_fid) {
269  parent_old_eids = {{parent_data.e02, parent_data.e03, parent_data.e23}};
270  } else {
271  parent_old_eids = {{parent_data.e12, parent_data.e13, parent_data.e23}};
272  }
273 
274 
275  assert(parent_merged_fid != -1);
276  assert(parent_new_tid != -1);
277 
278  for (int i = 0; i < 3; ++i) {
279  auto parent_to_child_data = Mesh::get_index_access(parent_to_child_accessor)
280  .const_vector_attribute(parent_old_eids[i]);
281 
282 
283  Tuple parent_tuple, child_tuple;
284  std::tie(parent_tuple, child_tuple) =
285  wmtk::multimesh::utils::vectors_to_tuples(parent_to_child_data);
286 
287  if (child_tuple.is_null()) {
288  // not child_tuple on this parent edge
289  continue;
290  }
291 
292 
293  bool child_tuple_exists = child_cell_flag_accessor.is_active(child_tuple);
294  if (!child_tuple_exists) {
295  continue;
296  }
297 
298  const int64_t parent_old_vid =
299  m.parent_scope([&]() { return m.id_vertex(parent_tuple); });
300 
301  int64_t parent_new_vid = -1;
302  if (parent_ear_fid_old != parent_merged_fid) {
303  // other side
304  if (parent_old_vid == parent_data.v0) {
305  parent_new_vid = parent_data.v1;
306  } else if (parent_old_vid == parent_data.v2) {
307  parent_new_vid = parent_data.v2;
308  } else if (parent_old_vid == parent_data.v3) {
309  parent_new_vid = parent_data.v3;
310  }
311  } else {
312  // same side
313  parent_new_vid = parent_old_vid;
314  }
315 
316  assert(parent_new_vid != -1);
317 
318  Tuple new_parent_tuple = m.tuple_from_global_ids(
319  parent_new_tid,
320  parent_merged_fid,
321  parent_new_eids[i],
322  parent_new_vid);
323 
324  update_pairs.push_back(std::make_pair(new_parent_tuple, child_tuple));
325  }
326 
327  for (const auto& pair : update_pairs) {
329  parent_to_child_accessor,
330  child_to_parent_accessor,
331  pair.first,
332  pair.second);
333  }
334  }
335  }
336  }
337  }
338 }
339 
340 
341 // edge -> edge
343  EdgeMesh&,
344  const simplex::Simplex&,
345  const edge_mesh::EdgeOperationData& parent_tmoe,
346  EdgeMesh&,
347  const simplex::Simplex&,
348  const edge_mesh::EdgeOperationData&) const
349 {
350  throw std::runtime_error("not implemented");
351 }
352 
353 // tri -> edge
355  TriMesh& parent_mesh,
356  const simplex::Simplex&,
357  const tri_mesh::EdgeOperationData& parent_tmoe,
358  EdgeMesh& child_mesh,
359  const simplex::Simplex&,
360  const edge_mesh::EdgeOperationData& child_emoe) const
361 {
362  const auto& parent_incident_datas = parent_tmoe.incident_face_datas();
363  const auto& parent_spine_v = parent_tmoe.incident_vids();
364 
365  auto& parent_mmmanager = parent_mesh.m_multi_mesh_manager;
366  auto& child_mmmanager = child_mesh.m_multi_mesh_manager;
367  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
368  int64_t child_id = child_mmmanager.child_id();
369  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
370  auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
371  auto parent_to_child_accessor = parent_mesh.create_accessor(parent_to_child_handle);
372 
373 
374  // update the new edges added by split
375  for (int64_t index = 0; index < 2; ++index) {
376  // we can choose f_parent on either side, here we choose 0
377  int64_t f_parent = parent_incident_datas[0].split_f[index];
378 
379  const int64_t e_child = child_emoe.m_split_e[index];
380  const int64_t e_parent = parent_tmoe.split_spine_eids[index];
381 
382  if (f_parent == -1 || e_child == -1 || e_parent == -1) {
383  continue;
384  }
385 
386  const int64_t v_child = child_emoe.m_spine_vids[index];
387  const int64_t v_parent = parent_spine_v[index];
388 
389  const Tuple parent_tuple = parent_mesh.tuple_from_global_ids(f_parent, e_parent, v_parent);
390  const Tuple child_tuple = child_mesh.tuple_from_global_ids(e_child, v_child);
391 
392  assert(parent_mesh.is_valid(parent_tuple));
393  assert(child_mesh.is_valid(child_tuple));
394 
396  parent_to_child_accessor,
397  child_to_parent_accessor,
398  parent_tuple,
399  child_tuple);
400  }
401 }
402 // tri -> tri
404  TriMesh& parent_mesh,
405  const simplex::Simplex&,
406  const tri_mesh::EdgeOperationData& parent_tmoe,
407  TriMesh& child_mesh,
408  const simplex::Simplex&,
409  const tri_mesh::EdgeOperationData& child_tmoe) const
410 {
411  // logger().trace(
412  // "UpdateEdgeOperationMultiMeshMapFunctor [{}=>{}] parent tmoe {} and child tmoe {}",
413  // fmt::join(parent_mesh.absolute_multi_mesh_id(), ","),
414  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
415  // wmtk::utils::TupleInspector::as_string(parent_tmoe.m_operating_tuple),
416  // wmtk::utils::TupleInspector::as_string(child_tmoe.m_operating_tuple));
417 
418  const auto& parent_incident_datas = parent_tmoe.incident_face_datas();
419  const auto& child_incident_datas = child_tmoe.incident_face_datas();
420 
421  const auto& child_spine_v = child_tmoe.incident_vids();
422  const auto& parent_spine_v = parent_tmoe.incident_vids();
423 
424 
425  auto& parent_mmmanager = parent_mesh.m_multi_mesh_manager;
426  auto& child_mmmanager = child_mesh.m_multi_mesh_manager;
427 
428  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
429 
430  int64_t child_id = child_mmmanager.child_id();
431  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
432  auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
433  auto parent_to_child_accessor = parent_mesh.create_accessor(parent_to_child_handle);
434 
435  // logger().trace(
436  // "Child had {} datas, parent had {} datas",
437  // child_incident_datas.size(),
438  // child_incident_datas.size());
439 
440  for (const auto& child_data : child_incident_datas) {
441  int64_t target_parent_fid = parent_global_cid(child_to_parent_accessor, child_data.fid);
442  // logger().trace(
443  // "[{}=>{}] child data started with gid {}->{} and parent had {}",
444  // fmt::join(parent_mesh.absolute_multi_mesh_id(), ","),
445  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
446  // child_data.fid,
447  // fmt::join(child_data.split_f, ","),
448  // target_parent_fid);
449 
450  for (const auto& parent_data : parent_incident_datas) {
451  // logger().trace(
452  // "Check for parent fid {} to be {} ({})",
453  // parent_data.fid,
454  // target_parent_fid,
455  // parent_data.fid == target_parent_fid);
456  if (parent_data.fid == target_parent_fid) {
457  // if there was a parent mapping we definitely need to update the edges
458  const auto& child_split_f = child_data.split_f;
459  const auto& parent_split_f = parent_data.split_f;
460 
461 
462  for (int64_t index = 0; index < 2; ++index) {
463  int64_t f_child = child_split_f[index];
464  int64_t f_parent = parent_split_f[index];
465  if (f_child == -1 || f_parent == -1) {
466  continue;
467  }
468 
469  int64_t e_child = child_data.ears[index].eid;
470  int64_t e_parent = parent_data.ears[index].eid;
471 
472  int64_t v_child = child_spine_v[index];
473  int64_t v_parent = parent_spine_v[index];
474 
475  const Tuple parent_tuple =
476  parent_mesh.tuple_from_global_ids(f_parent, e_parent, v_parent);
477  const Tuple child_tuple =
478  child_mesh.tuple_from_global_ids(f_child, e_child, v_child);
479  // logger().trace(
480  // "[{}=>{}] combining these setes of GIDS: Parent: {} {} {} {}; Child:
481  // {}
482  // {} "
483  // "{} {}",
484  // fmt::join(parent_mesh.absolute_multi_mesh_id(), ","),
485  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
486  // f_parent,
487  // e_parent,
488  // v_parent,
489 
490  // wmtk::utils::TupleInspector::as_string(parent_tuple),
491  // f_child,
492  // e_child,
493  // v_child,
494  // wmtk::utils::TupleInspector::as_string(child_tuple));
495 
496 
497  assert(parent_mesh.is_valid(parent_tuple));
498  assert(child_mesh.is_valid(child_tuple));
499 
501  parent_to_child_accessor,
502  child_to_parent_accessor,
503  parent_tuple,
504  child_tuple);
505  }
506  }
507  }
508  }
509 
510  // update_hash on neighboring cells. use only 2 to get the cell types on either case
511  // constexpr static PrimitiveType PV = PrimitiveType::Vertex;
512  // constexpr static PrimitiveType PE = PrimitiveType::Edge;
513  // constexpr static PrimitiveType PF = PrimitiveType::Triangle;
514 
515  // NOTE: this is purpuosely verbose to show a point
516  // We have to select with PrimitiveTypes are supported as children for each type of mesh
517  //
518  // logger().trace(
519  // "[{0}=>{1}] updating hashes for {0}",
520  // fmt::join(parent_mesh.absolute_multi_mesh_id(), ","),
521  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","));
522  // logger().trace(
523  // "[{0}=>{1}] updating hashes for {1}",
524  // fmt::join(parent_mesh.absolute_multi_mesh_id(), ","),
525  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","));
526 
527  // update_all_hashes(child_mesh,
528  // child_tmoe.global_ids_to_potential_tuples);
529 }
530 
531 // tet -> edge
533  TetMesh& parent_mesh,
534  const simplex::Simplex&,
535  const tet_mesh::EdgeOperationData& parent_tmoe,
536  EdgeMesh& child_mesh,
537  const simplex::Simplex&,
538  const edge_mesh::EdgeOperationData& child_emoe) const
539 {
540  const auto& parent_incident_tet_datas = parent_tmoe.incident_tet_datas();
541  const auto& parent_incident_face_datas = parent_tmoe.incident_face_datas();
542 
543  auto& parent_mmmanager = parent_mesh.m_multi_mesh_manager;
544  auto& child_mmmanager = child_mesh.m_multi_mesh_manager;
545 
546  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
547 
548  int64_t child_id = child_mmmanager.child_id();
549  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
550  auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
551  auto parent_to_child_accessor = parent_mesh.create_accessor(parent_to_child_handle);
552 
553  int64_t target_parent_tid =
554  parent_global_cid(child_to_parent_accessor, child_emoe.m_operating_edge_id);
555  int64_t target_parent_local_fid =
556  parent_local_fid(child_to_parent_accessor, child_emoe.m_operating_edge_id);
557  for (const auto& parent_data : parent_incident_tet_datas) {
558  if (parent_data.tid != target_parent_tid) continue;
559 
560  int64_t face_index = -1; // shoule be 0 or 1 after if
561  for (int i = 0; i < 2; ++i) {
562  if (parent_data.incident_face_local_fid[i] == target_parent_local_fid) {
563  // target_parent_global_fid =
564  // parent_incident_face_datas[parent_data.incident_face_data_idx[i]].fid;
565  face_index = i;
566  }
567  }
568  assert(face_index != -1);
569 
570  for (int index = 0; index < 2; ++index) {
571  const int64_t t_parent = parent_data.split_t[index];
572  const int64_t f_parent =
573  parent_incident_face_datas[parent_data.incident_face_data_idx[face_index]]
574  .split_f[index];
575 
576  const int64_t e_parent = parent_tmoe.new_spine_eids()[index];
577  const int64_t e_child = child_emoe.m_split_e[index];
578 
579  if (t_parent == -1 || f_parent == -1 || e_child == -1 || e_parent == -1) {
580  continue; // why?
581  }
582 
583  const int64_t v_parent = parent_tmoe.incident_vids()[index];
584  const int64_t v_child =
585  child_emoe.m_spine_vids[index]; // these two tuples are in inversed direction, also
586  // for tet->tri and tri->edge, shall we change?
587 
588  const Tuple parent_tuple =
589  parent_mesh.tuple_from_global_ids(t_parent, f_parent, e_parent, v_parent);
590  const Tuple child_tuple = child_mesh.tuple_from_global_ids(e_child, v_child);
591 
592  assert(parent_mesh.is_valid(parent_tuple));
593  assert(child_mesh.is_valid(child_tuple));
594 
596  parent_to_child_accessor,
597  child_to_parent_accessor,
598  parent_tuple,
599  child_tuple);
600  }
601  }
602 }
603 
604 // tet -> tri
606  TetMesh& parent_mesh,
607  const simplex::Simplex&,
608  const tet_mesh::EdgeOperationData& parent_tmoe,
609  TriMesh& child_mesh,
610  const simplex::Simplex&,
611  const tri_mesh::EdgeOperationData& child_fmoe) const
612 {
613  const auto& parent_incident_tet_datas = parent_tmoe.incident_tet_datas();
614  const auto& parent_incident_face_datas = parent_tmoe.incident_face_datas();
615 
616  const auto& child_incident_face_datas = child_fmoe.incident_face_datas();
617 
618  const auto& parent_spine_v = parent_tmoe.incident_vids();
619  const auto& child_spine_v = child_fmoe.incident_vids();
620 
621  auto& parent_mmmanager = parent_mesh.m_multi_mesh_manager;
622  auto& child_mmmanager = child_mesh.m_multi_mesh_manager;
623 
624  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
625 
626  int64_t child_id = child_mmmanager.child_id();
627  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
628  auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
629  auto parent_to_child_accessor = parent_mesh.create_accessor(parent_to_child_handle);
630 
631  for (const auto& child_data : child_incident_face_datas) {
632  int64_t target_parent_tid = parent_global_cid(child_to_parent_accessor, child_data.fid);
633  // get parent local fid or global fid?
634  // try local here
635  int64_t target_parent_local_fid =
636  parent_local_fid(child_to_parent_accessor, child_data.fid);
637 
638  for (const auto& parent_data : parent_incident_tet_datas) {
639  if (parent_data.tid != target_parent_tid) continue;
640  int64_t face_index = -1; // shoule be 0 or 1 after if
641  for (int i = 0; i < 2; ++i) {
642  if (parent_data.incident_face_local_fid[i] == target_parent_local_fid) {
643  // target_parent_global_fid =
644  // parent_incident_face_datas[parent_data.incident_face_data_idx[i]].fid;
645  face_index = i;
646  }
647  }
648  assert(face_index != -1);
649 
650  for (int index = 0; index < 2; ++index) {
651  // should check if parent child tuples are in the same orientation
652  int64_t t_parent = parent_data.split_t[index];
653 
654  int64_t f_child = child_data.split_f[index];
655  int64_t f_parent =
656  parent_incident_face_datas[parent_data.incident_face_data_idx[face_index]]
657  .split_f[index];
658 
659  if (t_parent == -1 || f_child == -1 || f_parent == -1) {
660  continue;
661  }
662 
663  int64_t e_child = child_data.ears[index].eid;
664  int64_t e_parent =
665  parent_incident_face_datas[parent_data.incident_face_data_idx[face_index]]
666  .ear_eids[index];
667 
668  int64_t v_child = child_spine_v[index];
669  int64_t v_parent = parent_spine_v[index];
670 
671  const Tuple parent_tuple =
672  parent_mesh.tuple_from_global_ids(t_parent, f_parent, e_parent, v_parent);
673  const Tuple child_tuple =
674  child_mesh.tuple_from_global_ids(f_child, e_child, v_child);
675 
676  assert(parent_mesh.is_valid(parent_tuple));
677  assert(child_mesh.is_valid(child_tuple));
678 
680  parent_to_child_accessor,
681  child_to_parent_accessor,
682  parent_tuple,
683  child_tuple);
684  }
685  }
686  }
687 }
688 
689 // tet -> tet
691  TetMesh& parent_mesh,
692  const simplex::Simplex&,
693  const tet_mesh::EdgeOperationData& parent_tmoe,
694  TetMesh& child_mesh,
695  const simplex::Simplex&,
696  const tet_mesh::EdgeOperationData& child_tmoe) const
697 {
698  const auto& parent_incident_tet_datas = parent_tmoe.incident_tet_datas();
699  const auto& child_incident_tet_datas = child_tmoe.incident_tet_datas();
700 
701  const auto& parent_incident_face_datas = parent_tmoe.incident_face_datas();
702  const auto& child_incident_face_datas = child_tmoe.incident_face_datas();
703 
704  const auto& parent_spine_v = parent_tmoe.incident_vids();
705  const auto& child_spine_v = child_tmoe.incident_vids();
706 
707  auto& parent_mmmanager = parent_mesh.m_multi_mesh_manager;
708  auto& child_mmmanager = child_mesh.m_multi_mesh_manager;
709 
710  auto child_to_parent_handle = child_mmmanager.map_to_parent_handle;
711 
712  int64_t child_id = child_mmmanager.child_id();
713  auto parent_to_child_handle = parent_mmmanager.children().at(child_id).map_handle;
714  auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
715  auto parent_to_child_accessor = parent_mesh.create_accessor(parent_to_child_handle);
716 
717  for (const auto& child_data : child_incident_tet_datas) {
718  int64_t target_parent_tid = parent_global_cid(child_to_parent_accessor, child_data.tid);
719 
720  for (const auto& parent_data : parent_incident_tet_datas) {
721  if (parent_data.tid != target_parent_tid) continue;
722  const auto& child_split_t = child_data.split_t;
723  const auto& parent_split_t = parent_data.split_t;
724 
725  for (int64_t index = 0; index < 2; ++index) {
726  int64_t t_child = child_split_t[index];
727  int64_t t_parent = parent_split_t[index];
728 
729  if (t_child == -1 || t_parent == -1) {
730  continue; // TODO: why need this check?
731  }
732 
733  int64_t f_child = child_data.ears[index].fid;
734  int64_t f_parent = parent_data.ears[index].fid;
735 
736  int64_t e_child =
737  child_incident_face_datas[child_data.incident_face_data_idx[1]].ear_eids[index];
738  int64_t e_parent = parent_incident_face_datas[parent_data.incident_face_data_idx[1]]
739  .ear_eids[index];
740 
741  int64_t v_child = child_spine_v[index];
742  int64_t v_parent = parent_spine_v[index];
743 
744  // TODO: why is this tuple selected? why not others?
745  const Tuple parent_tuple =
746  parent_mesh.tuple_from_global_ids(t_parent, f_parent, e_parent, v_parent);
747  const Tuple child_tuple =
748  child_mesh.tuple_from_global_ids(t_child, f_child, e_child, v_child);
749 
750  assert(parent_mesh.is_valid(parent_tuple));
751  assert(child_mesh.is_valid(child_tuple));
752 
754  parent_to_child_accessor,
755  child_to_parent_accessor,
756  parent_tuple,
757  child_tuple);
758  }
759  }
760  }
761 }
762 
763 
764 // edge
766  EdgeMesh& parent_mesh,
767  const simplex::Simplex&,
768  const edge_mesh::EdgeOperationData& parent_emoe)
769 {
770  return;
771  // if there's a child mesh then lets disallow this
772 #if !defined(NDEBUG)
773  if (parent_mesh.get_child_meshes().size() > 0) {
774  throw std::runtime_error("not implemented");
775  }
776 #endif
777  logger().error("EdgeMesh update Not implemented!");
778 }
779 
780 // tri
782  TriMesh& parent_mesh,
783  const simplex::Simplex&,
784  const tri_mesh::EdgeOperationData& parent_fmoe)
785 {
786  std::vector<std::tuple<int64_t, std::array<int64_t, 2>>> parent_split_cell_maps;
787  const auto& parent_incident_datas = parent_fmoe.incident_face_datas();
788  for (const auto& parent_data : parent_incident_datas) {
789  if (parent_data.split_f[0] == -1) break;
790  parent_split_cell_maps.emplace_back(parent_data.fid, parent_data.split_f);
791  }
792  // TODO: update the ear edges here?
793 
794  if (parent_fmoe.is_collapse) {
795  update_ear_replacement(parent_mesh, parent_fmoe);
796  }
798  parent_mesh,
799  parent_fmoe.global_ids_to_potential_tuples,
800  parent_split_cell_maps);
801 }
802 
803 // tet
805  TetMesh& parent_mesh,
806  const simplex::Simplex&,
807  const tet_mesh::EdgeOperationData& parent_tmoe)
808 {
809  std::vector<std::tuple<int64_t, std::array<int64_t, 2>>> parent_split_cell_maps;
810  const auto& parent_incident_tet_datas = parent_tmoe.incident_tet_datas();
811  for (const auto& parent_data : parent_incident_tet_datas) {
812  if (parent_data.split_t[0] == -1) break; // no split datas, not a split function
813  parent_split_cell_maps.emplace_back(parent_data.tid, parent_data.split_t);
814  }
815 
816  if (parent_tmoe.is_collapse) {
817  update_ear_replacement(parent_mesh, parent_tmoe);
818  }
820  parent_mesh,
821  parent_tmoe.global_ids_to_potential_tuples,
822  parent_split_cell_maps);
823 }
824 
827  int64_t parent_gid) const
828 {
829  return MultiMeshManager::child_global_cid(parent_to_child, parent_gid);
830 }
833  int64_t child_gid) const
834 {
835  return MultiMeshManager::parent_global_cid(child_to_parent, child_gid);
836 }
837 
840  int64_t child_gid) const
841 {
842  return MultiMeshManager::parent_local_fid(child_to_parent, child_gid);
843 }
844 
845 
846 /*
847 template <typename MeshType>
848 void UpdateEdgeOperationMultiMeshMapFunctor::update_maps(
849  MeshType& mesh,
850  const simplex::Simplex&,
851  const EdgeOperationData&)
852 {
853  // on split:
854  // for each dimension
855  // for each boundary simplex
856  // update boundary facets using availalbe simplices (in split we have 2 choices,
857  // collapse we have to look at opposing ears each simplex that refers to an existing
858  // simplex must be replaced
859  //
860  // on collapse:
861  // for each dimension
862  // for each boundary simplex
863  // if the face used an ear simplex
864  // update boundary facets using availalbe simplices (in split we have 2 choices,
865  // collapse we have to look at opposing ears each simplex that refers to an existing
866  // simplex must be replaced
867  //
868  //
869 
870 
871  for (size_t j = 0; j < simplices_to_update.size(); ++j) {
872  mesh.m_multi_mesh_manager
873  .update_map_tuple_hashes(m, PTs[j], simplices_to_update[j], split_cell_maps);
874  }
875 }
876 */
877 
878 } // namespace wmtk::operations::utils
Tuple tuple_from_global_ids(int64_t eid, int64_t vid) const
Definition: EdgeMesh.cpp:196
bool is_valid(const Tuple &tuple) const final override
check validity of tuple including its hash
Definition: EdgeMesh.cpp:214
attribute::Accessor< T, Derived, Dim > create_accessor(const TypedAttributeHandle< T > &handle)
constructs an accessor that is aware of the derived mesh's type
Definition: MeshCRTP.hpp:67
static auto & get_index_access(attribute::Accessor< T, MeshType > &attr)
Definition: Mesh.hpp:824
multimesh::MultiMeshManager m_multi_mesh_manager
Definition: Mesh.hpp:842
decltype(auto) parent_scope(Functor &&f, Args &&... args) const
Evaluate the passed in function inside the parent scope.
std::vector< std::shared_ptr< Mesh > > get_child_meshes() const
returns the direct multimesh child meshes for the current mesh
Tuple tuple_from_global_ids(int64_t tid, int64_t fid, int64_t eid, int64_t vid) const
Definition: TetMesh.cpp:583
int64_t id_vertex(const Tuple &tuple) const
Definition: TetMesh.hpp:70
int64_t id_edge(const Tuple &tuple) const
Definition: TetMesh.hpp:71
bool is_valid(const Tuple &tuple) const final override
check validity of tuple including its hash
Definition: TetMesh.cpp:320
int64_t id_vertex(const Tuple &tuple) const
Definition: TriMesh.hpp:74
bool is_valid(const Tuple &tuple) const final override
check validity of tuple including its hash
Definition: TriMesh.cpp:329
Tuple tuple_from_global_ids(int64_t fid, int64_t eid, int64_t vid) const
Definition: TriMesh.cpp:245
bool is_null() const
Checks if a tuple is "null". This merely implies the global index is -1.
Definition: Tuple.hxx:40
A CachingAccessor that uses tuples for accessing attributes instead of indices.
Definition: Accessor.hpp:25
int64_t child_id() const
Specifies the child id of this mesh if it a child mesh in a mult-mesh tree.
static int64_t child_global_cid(const wmtk::attribute::Accessor< int64_t > &parent_to_child, int64_t parent_gid)
static int64_t parent_local_fid(const wmtk::attribute::Accessor< int64_t > &child_to_parent, int64_t child_gid)
static int64_t parent_global_cid(const wmtk::attribute::Accessor< int64_t > &child_to_parent, int64_t child_gid)
TypedAttributeHandle< int64_t > map_to_parent_handle
void update_map_tuple_hashes(Mesh &my_mesh, PrimitiveType primitive_type, const std::vector< std::tuple< int64_t, std::vector< Tuple >>> &simplices_to_update, const std::vector< std::tuple< int64_t, std::array< int64_t, 2 >>> &split_cell_maps={})
std::vector< std::vector< std::tuple< int64_t, std::vector< Tuple > > > > global_ids_to_potential_tuples
std::vector< IncidentTetData > incident_tet_datas() const
const std::array< int64_t, 2 > & incident_vids() const
std::array< int64_t, 2 > new_spine_eids() const
std::vector< IncidentFaceData > incident_face_datas() const
const std::array< int64_t, 2 > & incident_vids() const
const std::vector< IncidentFaceData > & incident_face_datas() const
void update_ear_replacement(TriMesh &m, const tri_mesh::EdgeOperationData &fmoe) const
int64_t parent_global_cid(const attribute::Accessor< int64_t, Mesh, Eigen::Dynamic > &parent_to_child, int64_t parent_gid) const
int64_t parent_local_fid(const attribute::Accessor< int64_t, Mesh, Eigen::Dynamic > &parent_to_child, int64_t parent_gid) const
void operator()(EdgeMesh &, const simplex::Simplex &, const edge_mesh::EdgeOperationData &parent_tmoe, EdgeMesh &, const simplex::Simplex &, const edge_mesh::EdgeOperationData &) const
int64_t child_global_cid(const attribute::Accessor< int64_t, Mesh, Eigen::Dynamic > &parent_to_child, int64_t parent_gid) const
void update_all_hashes(Mesh &m, const std::vector< std::vector< std::tuple< int64_t, std::vector< Tuple >>>> &simplices_to_update, const std::vector< std::tuple< int64_t, std::array< int64_t, 2 >>> &split_cell_maps={}) const
constexpr wmtk::PrimitiveType PT
constexpr wmtk::PrimitiveType PF
std::tuple< Tuple, Tuple > vectors_to_tuples(const Eigen::Ref< const TwoTupleVector > &v)
void symmetric_write_tuple_map_attributes(wmtk::attribute::Accessor< int64_t, MeshA > &a_to_b, wmtk::attribute::Accessor< int64_t, MeshB > &b_to_a, const Tuple &a_tuple, const Tuple &b_tuple)
constexpr PrimitiveType PV
spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:58
constexpr PrimitiveType PE