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