DSC
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
is_mesh.h
1 //
2 // Deformabel Simplicial Complex (DSC) method
3 // Copyright (C) 2013 Technical University of Denmark
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // See licence.txt for a copy of the GNU General Public License.
16 
17 #pragma once
18 
19 #include <functional>
20 #include <thread>
21 #include "util.h"
22 #include "kernel.h"
23 #include "simplex.h"
24 #include "simplex_set.h"
25 #include "is_mesh_iterator.h"
26 #include "geometry.h"
27 #include "attribute_vector.h"
28 
29 namespace is_mesh {
30 
32  std::vector<NodeKey> nodeKeys;
33  std::vector<EdgeKey> edgeKeys;
34  std::vector<FaceKey> faceKeys;
35  std::vector<TetrahedronKey> tetrahedronKeys;
36  };
37 
38  class Geometry;
39 
40  class ISMesh
41  {
42  kernel<NodeKey,Node> m_node_kernel;
43  kernel<EdgeKey,Edge> m_edge_kernel;
44  kernel<FaceKey,Face> m_face_kernel;
45  kernel<TetrahedronKey,Tetrahedron> m_tetrahedron_kernel;
46 
47  std::shared_ptr<Geometry> subdomain;
48 
49  std::map<long,std::function<void(const GarbageCollectDeletions&)>> m_gc_listeners;
50  std::map<long,std::function<void(const TetrahedronKey& tid, unsigned int oldValue)>> m_set_label_listeners;
51  std::map<long,std::function<void(const NodeKey& nid_new, const NodeKey& nid1, const NodeKey& nid2)>> m_split_listeners;
52  std::map<long,std::function<void(const NodeKey& nid, const NodeKey& nid_removed, double weight)>> m_collapse_listeners;
53 
54  unsigned int m_number_of_threads = std::thread::hardware_concurrency();
55  public:
56  ISMesh(std::vector<vec3> & points, std::vector<int> & tets, const std::vector<int>& tet_labels);
57 
58  // copy of ISMesh is rare. marked explicit to avoid copying the object by mistake (such as pass by value)
59  // if mesh has subdomain is is not copied
60  explicit ISMesh(const ISMesh& mesh);
61 
62  ~ISMesh();
63 
64  unsigned int get_no_nodes() const;
65 
66  unsigned int get_no_edges() const;
67 
68  unsigned int get_no_faces() const;
69 
70  unsigned int get_no_tets() const;
71 
72  unsigned int get_max_node_key() const;
73 
74  unsigned int get_max_edge_key() const;
75 
76  unsigned int get_max_face_key() const;
77 
78  unsigned int get_max_tet_key() const;
79 
80  std::shared_ptr<Geometry> get_subdomain();
81 
82  void clear_subdomain();
83 
84  void set_subdomain(std::shared_ptr<Geometry> subdomain);
85 
86  unsigned int get_number_of_threads() const;
87 
88  void set_number_of_threads(unsigned int m_number_of_threads);
89 
91  // ITERATORS //
93  public:
94  std::vector<TetrahedronKey> find_par_tet(std::function<bool(Tetrahedron&)> include){ return find_par<TetrahedronKey,Tetrahedron>(include); }
95  std::vector<FaceKey> find_par_face(std::function<bool(Face&)> include){ return find_par<FaceKey,Face>(include); }
96  std::vector<EdgeKey> find_par_edge(std::function<bool(Edge&)> include){ return find_par<EdgeKey,Edge>(include); }
97  std::vector<NodeKey> find_par_node(std::function<bool(Node&)> include){ return find_par<NodeKey,Node>(include); }
98 
99  template<typename key_type, typename value_type>
100  std::vector<key_type> find_par(std::function<bool(value_type&)> include);
101 
102  // Runs the function fn on each node simultaneously on many threads
103  // Number of threads used is std::thread::hardware_concurrency()
104  template<typename value_type>
105  void for_each_par(std::function<void(value_type&,int)> fn);
106 
107  // Map each element to a return type using map_fn and then reduce the return value into a single value using reduce_fn
108  template<typename simplex_type, typename return_type>
109  return_type map_reduce_par(std::function<return_type(simplex_type&)> map_fn, std::function<return_type(return_type,return_type)> reduce_fn, return_type default_value = {});
110 
111  // Space partitioned parallel for each
112  // Runs the function fn on each node simultaneously on many threads
113  // Number of threads used is std::thread::hardware_concurrency()
114  // partitionsize must be larger than twice the maximum node size
115  // the function is evaluated once for each simplex
116  // dimension is on which axis the space is partitioned (x,y or z)
117  template<typename value_type>
118  void for_each_par_sp(double partitionsize, int dimension, std::function<void(value_type& node, int threadid)> fn);
119 
120  NodeIterator nodes() const;
121 
122  EdgeIterator edges() const;
123 
124  FaceIterator faces() const;
125 
126  TetrahedronIterator tetrahedra() const;
127 
128  public:
129  void set_label(const TetrahedronKey& tid, int label);
130 
131  private:
132  template<typename key_type, typename value_type>
133  kernel<key_type,value_type>& get_kernel();
134 
135  struct edge_key {
136  int k1, k2;
137  edge_key(int i, int j) : k1(i), k2(j) {}
138  bool operator<(const edge_key& k) const
139  {
140  return k1 < k.k1 || (k1 == k.k1 && k2 < k.k2);
141  }
142  };
143  struct face_key
144  {
145  int k1, k2, k3;
146  face_key(int i, int j, int k) : k1(i), k2(j), k3(k){}
147  bool operator<(const face_key& k) const
148  {
149  // return k1 < k.k1 || (k1 == k.k1 && k2 < k.k2 || (k2 == k.k2 && k3 < k.k3)) ;
150  if (k1 < k.k1) return true;
151  if (k1 == k.k1 && k2 < k.k2) return true;
152  if (k1 == k.k1 && k2 == k.k2 && k3 < k.k3) return true;
153  return false;
154  }
155  };
156 
157  template<typename map_type, typename mesh_type>
158  inline int create_edge(int i, int j, map_type& edge_map, mesh_type& mesh)
159  {
160  int a,b;
161  if (i <= j) { a = i; b = j; }
162  else { a = j; b = i; }
163  edge_key key(a, b);
164  auto it = edge_map.find(key);
165  if (it == edge_map.end())
166  {
167  int n = mesh.insert_edge(i, j); //non-sorted
168  it = edge_map.insert(std::pair<edge_key,int>(key, n)).first;
169  }
170  return it->second;
171  }
172 
173  template<typename map_type, typename mesh_type>
174  inline int create_face(int i, int j, int k, map_type& face_map, mesh_type& mesh)
175  {
176  int a[3] = {i, j, k};
177  std::sort(a, a+3);
178  face_key key(a[0], a[1], a[2]);
179  auto it = face_map.find(key); //lookup in sorted order
180  if (it == face_map.end())
181  {
182  int index = mesh.insert_face(i, j, k); //create in supplied order
183  it = face_map.insert(std::pair<face_key,int>(key, index)).first;
184  }
185  return it->second;
186  }
187 
188  bool create(const std::vector<vec3>& points, const std::vector<int>& tets);
192  void init_flags(const std::vector<int>& tet_labels);
193 
197  void update_flag();
198 
202  void update_flag(const SimplexSet<TetrahedronKey>& tids);
203 
204  void update_flag(const FaceKey & f);
205 
206  void update_flag(const EdgeKey & e);
207 
208  void connected_component(SimplexSet<TetrahedronKey>& tids, const TetrahedronKey& tid);
209 
210  bool crossing(const NodeKey& n);
211 
212 
213  void update_flag(const NodeKey & n);
214 
216  // GETTER FUNCTIONS //
218  public:
219  Node & get(const NodeKey& nid);
220 
221  Edge & get(const EdgeKey& eid);
222 
223  Face & get(const FaceKey& fid);
224 
225  Tetrahedron & get(const TetrahedronKey& tid);
226 
227  const Node & get(const NodeKey& nid) const ;
228 
229  const Edge & get(const EdgeKey& eid) const ;
230 
231  const Face & get(const FaceKey& fid) const ;
232 
233  const Tetrahedron & get(const TetrahedronKey& tid) const ;
234 
235  // Getters for getting the boundary of a boundary etc.
236 
237  SimplexSet<NodeKey> get_sorted_nodes(const FaceKey& fid, const TetrahedronKey& tid);
238 
239  SimplexSet<NodeKey> get_sorted_nodes(const FaceKey& fid);
240 
241  // Getters which have a SimplexSet as input
242  template<typename key_type>
243  SimplexSet<NodeKey> get_nodes(const SimplexSet<key_type>& keys)
244  {
245  SimplexSet<NodeKey> nids;
246  for(auto k : keys)
247  {
248  nids += get(k).node_keys();
249  }
250  return nids;
251  }
252 
253  template<typename key_type>
254  SimplexSet<EdgeKey> get_edges(const SimplexSet<key_type>& keys)
255  {
256  SimplexSet<EdgeKey> eids;
257  for(auto k : keys)
258  {
259  eids += get(k).edge_keys();
260  }
261  return eids;
262  }
263 
264 
265  template<typename key_type>
266  SimplexSet<FaceKey> get_faces(const SimplexSet<key_type>& keys)
267  {
268  SimplexSet<FaceKey> fids;
269  for(auto k : keys)
270  {
271  fids += get(k).face_keys();
272  }
273  return fids;
274  }
275 
276  template<typename key_type>
278  {
280  for(auto k : keys)
281  {
282  tids += get(k).tet_keys();
283  }
284  return tids;
285  }
286 
287  // Other getter functions
291  NodeKey get_node(const EdgeKey& eid1, const EdgeKey& eid2);
295  NodeKey get_node(const EdgeKey& eid, const NodeKey& nid);
299  EdgeKey get_edge(const NodeKey& nid1, const NodeKey& nid2);
303  EdgeKey get_edge(const FaceKey& fid1, const FaceKey& fid2);
307  FaceKey get_face(const NodeKey& nid1, const NodeKey& nid2, const NodeKey& nid3);
311  FaceKey get_face(const TetrahedronKey& tid1, const TetrahedronKey& tid2);
315  TetrahedronKey get_tet(const TetrahedronKey& tid, const FaceKey& fid);
319  std::vector<vec3> get_pos(const SimplexSet<NodeKey>& nids);
320 
322  // EXISTS FUNCTIONS //
324  public:
325 
326  bool exists(const TetrahedronKey& t);
327 
328  bool exists(const FaceKey& f);
329 
330  bool exists(const EdgeKey& e);
331 
332  bool exists(const NodeKey& n);
333 
334 
335  bool excluded(const TetrahedronKey& t);
336 
337  bool excluded(const FaceKey& f);
338 
339  bool excluded(const EdgeKey& e);
340 
341  bool excluded(const NodeKey& n);
342 
343 
345  // ORIENTATION FUNCTIONS //
347 
348  public:
349  bool is_clockwise_order(const NodeKey& nid, SimplexSet<NodeKey>& nids);
350  /*
351  * Orient the nodes in a counter clockwise order seen from the node a.
352  */
353  void orient_cc(const NodeKey& nid, SimplexSet<NodeKey>& nids);
357  bool is_inverted(const TetrahedronKey& tid);
358 
359  bool is_inverted_destination(const TetrahedronKey& tid);
360 
362  // MESH FUNCTIONS //
364 
365  public:
369  NodeKey insert_node(const vec3& p);
374  EdgeKey insert_edge(NodeKey node1, NodeKey node2);
379  FaceKey insert_face(EdgeKey edge1, EdgeKey edge2, EdgeKey edge3);
384  TetrahedronKey insert_tetrahedron(FaceKey face1, FaceKey face2, FaceKey face3, FaceKey face4);
385 
386  private:
387  void remove(const NodeKey& nid);
388 
389  void remove(const EdgeKey& eid);
390 
391  void remove(const FaceKey& fid);
392 
393  void remove(const TetrahedronKey& tid);
394 
395  NodeKey merge(const NodeKey& key1, const NodeKey& key2);
396 
397  template<typename child_key, typename parent_key>
398  void connect(const child_key& ck, const parent_key& pk)
399  {
400  get(ck).add_co_face(pk);
401  get(pk).add_face(ck);
402  }
403 
404  template<typename child_key, typename parent_key>
405  void disconnect(const child_key& ck, const parent_key& pk)
406  {
407  get(ck).remove_co_face(pk);
408  get(pk).remove_face(ck);
409  }
410 
411  template<typename child_key, typename parent_key>
412  void swap(const child_key& ck1, const parent_key& pk1, const child_key& ck2, const parent_key& pk2)
413  {
414  if(!get(pk1).get_boundary().contains(ck1))
415  {
416  assert(get(pk1).get_boundary().contains(ck2));
417  assert(get(pk2).get_boundary().contains(ck1));
418 
419  disconnect(ck1, pk2);
420  disconnect(ck2, pk1);
421  connect(ck1, pk1);
422  connect(ck2, pk2);
423  }
424  else {
425  assert(get(pk1).get_boundary().contains(ck1));
426  assert(get(pk2).get_boundary().contains(ck2));
427 
428  disconnect(ck1, pk1);
429  disconnect(ck2, pk2);
430  connect(ck1, pk2);
431  connect(ck2, pk1);
432  }
433  }
434 
435  template<typename key_type>
436  key_type merge(const key_type& key1, const key_type& key2)
437  {
438  auto& simplex = get(key2);
439  for(auto k : simplex.get_co_boundary())
440  {
441  connect(key1, k);
442  }
443  for(auto k : simplex.get_boundary())
444  {
445  connect(k, key1);
446  }
447  remove(key2);
448  return key1;
449  }
450 
451  public:
456  vec3 get_barycenter(const SimplexSet<NodeKey>& nids, bool interface = false);
457 
458  NodeKey split(const EdgeKey& eid, const vec3& pos, const vec3& destination);
459 
460 
464  void collapse(const EdgeKey& eid, const NodeKey& nid, double weight = 0.5);
465 
466  FaceKey flip_32(const EdgeKey& eid);
467 
468  EdgeKey flip_23(const FaceKey& fid);
469 
470  void flip(const EdgeKey& eid, const FaceKey& fid1, const FaceKey& fid2);
471 
472 
473  void flip_22(const FaceKey& fid1, const FaceKey& fid2);
474 
475  void flip_44(const FaceKey& fid1, const FaceKey& fid2);
476 
477  private:
478  void update_split(const NodeKey& nid_new, const NodeKey& nid1, const NodeKey& nid2);
479 
480  void update_collapse(const NodeKey& nid, const NodeKey& nid_removed, double weight);
481 
483  // UTILITY FUNCTIONS //
485  public:
486 
487  double volume_destination(const is_mesh::SimplexSet<is_mesh::NodeKey>& nids);
488 
489  double signed_volume_destination(const is_mesh::SimplexSet<is_mesh::NodeKey>& nids);
490 
491  void garbage_collect();
492 
493  virtual void scale(const vec3& s);
494 
495  void extract_surface_mesh(std::vector<vec3>& points, std::vector<int>& faces);
496 
497  // extract all tests as tet surfaces
498  void extract_surface_mesh_debug(std::vector<vec3>& points, std::vector<int>& faces);
499 
500  void extract_tet_mesh(std::vector<vec3>& points, std::vector<int>& tets, std::vector<int>& tet_labels);
501 
502  void validity_check(bool skip_boundary_check = false);
503 
504  // subscribe for gc events - needed if you are working with persistent attribute_vectors
505  // returns listener id
506  long add_gc_listener(std::function<void(const GarbageCollectDeletions&)> fn);
507 
508  // remove listener by id
509  bool remove_gc_listener(long id);
510 
511  long add_label_listener(std::function<void(const TetrahedronKey& tid, unsigned int oldValue)> fn);
512 
513  bool remove_label_listener(long id);
514 
515  long add_split_listener(std::function<void(const NodeKey& nid_new, const NodeKey& nid1, const NodeKey& nid2)> fn);
516 
517  bool remove_split_listener(long id);
518 
519  long add_collapse_listener(std::function<void(const NodeKey& nid, const NodeKey& nid_removed, double weight)> fn);
520 
521  bool remove_collapse_listener(long id);
522 
523  friend class Node;
524  friend class Edge;
525  friend class Face;
526  friend class Tetrahedron;
527  };
528 
529  template<typename key_type, typename value_type>
530  inline void run_for_each_par(std::function<void(value_type&,int)> fn, kernel<key_type,value_type> *kernel, int from, int to, int threadid){
531  auto begin = kernel->find_valid_iterator(key_type(std::min(from, (int)kernel->capacity())));
532  auto end = kernel->find_valid_iterator(key_type(std::min(to, (int)kernel->capacity())));
533  for (auto iter = begin;iter!=end;iter++){
534  auto& n = *iter;
535  fn(n,threadid);
536  }
537  }
538 
539  template<typename value_type>
540  inline void ISMesh::for_each_par(std::function<void(value_type&,int)> fn) {
541  using KeyType = decltype(std::declval<value_type>().key()); // the type of value().key()
542  auto kernel = &get_kernel<KeyType, value_type>();
543  kernel->readonly = true;
544 
545  int thread_count = m_number_of_threads;
546  if (thread_count<=1){
547  for (auto &n : *kernel){
548  fn(n,0);
549  }
550  } else {
551  std::vector<std::thread *> threads;
552  int chunk_size = (int) ceil(kernel->capacity() / (float) (thread_count));
553 
554  for (int i = 0; i < thread_count; i++) {
555  threads.push_back(new std::thread(run_for_each_par<KeyType, value_type>, fn, kernel, i * chunk_size, (1 + i) * chunk_size, i));
556  }
557 
558  for (int i = 0; i < thread_count; i++) {
559  threads[i]->join();
560  delete threads[i];
561  }
562  }
563  kernel->readonly = false;
564  }
565 
566  template<typename simplex_type, typename return_type>
567  inline return_type ISMesh::map_reduce_par(std::function<return_type(simplex_type&)> map_fn, std::function<return_type(return_type,return_type)> reduce_fn, return_type default_value){
568  std::vector<return_type> res(m_number_of_threads, default_value);
569  for_each_par<simplex_type>([&](simplex_type& v, int index){
570  auto value = map_fn(v);
571  res[index] = reduce_fn(res[index],value);
572  });
573  for (int i=1;i<res.size();i++){
574  res[i] = reduce_fn(res[i-1], res[i]);
575  }
576  return res[res.size()-1];
577  }
578 
579  template<typename key_type, typename value_type>
580  inline std::vector<key_type> ISMesh::find_par(std::function<bool(value_type&)> include){
581  std::vector<std::vector<key_type>> res_array(m_number_of_threads, {});
582  for_each_par<value_type>([&](value_type &value, int threadid){
583  if (include(value))
584  {
585  res_array[threadid].push_back(value.key());
586  }
587  });
588  std::vector<key_type> res;
589  for (auto & t:res_array){
590  res.insert(res.end(), t.begin(), t.end());
591  }
592  return res;
593  }
594 
595  template<typename value_type, typename kernel_type, typename key_type>
596  inline void run_for_each_par_sp(std::function<void(value_type&,int)> fn, kernel_type* kernel, int threadid, int actualthread, AttributeVector<key_type, int> *attributeVector){
597  for (int i=0;i< attributeVector->size();i++){
598  key_type key(i);
599  int run_in_thread = (*attributeVector)[key];
600  if (run_in_thread == threadid){
601  fn(kernel->get(key), actualthread);
602  }
603  }
604  }
605 
606  template<typename value_type>
607  inline void ISMesh::for_each_par_sp(double partitionsize, int dimension, std::function<void(value_type&,int)> fn) {
608  using KeyType = decltype(std::declval<value_type>().key()); // the type of value().key()
609  using KernelType = kernel<KeyType, value_type>;
610  auto kernel = &get_kernel<KeyType, value_type>();
611  kernel->readonly = true;
612 
613  if (m_number_of_threads <=1){
614  for (auto &n : *kernel){
615  fn(n,0);
616  }
617  } else {
618  AttributeVector<KeyType, int> attributeVector(kernel->capacity(), -1);
619  for_each_par<value_type>([&](value_type& n, int t){
620  double p = n.get_center()[dimension];
621  double concur_partitionsize = partitionsize * m_number_of_threads * 2;
622  if (p < 0) {
623  p += concur_partitionsize * (int) (ceil(-p / concur_partitionsize));
624  }
625  p = fmod(p, concur_partitionsize);
626  int run_in_thread = std::min((int) floor(p / partitionsize), ((int) m_number_of_threads * 2) - 1);
627  attributeVector[n.key()] = run_in_thread;
628  });
629 
630  std::vector<std::thread*> threads;
631  for (int i=0;i< m_number_of_threads;i++){
632  threads.push_back(new std::thread(run_for_each_par_sp<value_type, KernelType, KeyType>, fn, kernel, i*2,i, &attributeVector));
633  }
634  for (int i=0;i< m_number_of_threads;i++){
635  threads[i]->join();
636  }
637  for (int i=0;i< m_number_of_threads;i++){
638  delete threads[i];
639  threads[i] = new std::thread(run_for_each_par_sp<value_type, KernelType, KeyType>, fn, kernel, 1+i*2,i, &attributeVector);
640  }
641  for (int i=0;i< m_number_of_threads;i++){
642  threads[i]->join();
643  delete threads[i];
644  }
645  }
646  kernel->readonly = false;
647  }
648 
649  template<>
650  inline kernel<NodeKey,Node>& ISMesh::get_kernel(){
651  return m_node_kernel;
652  }
653 
654  template<>
655  inline kernel<EdgeKey,Edge>& ISMesh::get_kernel(){
656  return m_edge_kernel;
657  }
658 
659  template<>
660  inline kernel<FaceKey,Face>& ISMesh::get_kernel(){
661  return m_face_kernel;
662  }
663 
664  template<>
665  inline kernel<TetrahedronKey,Tetrahedron>& ISMesh::get_kernel(){
666  return m_tetrahedron_kernel;
667  }
668 }
TetrahedronKey insert_tetrahedron(FaceKey face1, FaceKey face2, FaceKey face3, FaceKey face4)
Definition: is_mesh.cpp:634
Definition: geometry.h:24
Definition: face.h:27
TetrahedronKey get_tet(const TetrahedronKey &tid, const FaceKey &fid)
Definition: is_mesh.cpp:498
Definition: is_mesh_iterator.h:60
Definition: node.h:27
Definition: key.h:75
A 3D double vector.
Definition: Vec3d.h:26
size_t capacity() const
Definition: kernel.h:159
void collapse(const EdgeKey &eid, const NodeKey &nid, double weight=0.5)
Definition: is_mesh.cpp:776
Definition: tetrahedron.h:27
Definition: is_mesh_iterator.h:49
Definition: is_mesh.h:31
Definition: is_mesh_iterator.h:29
Definition: edge.h:27
Definition: key.h:89
bool is_inverted(const TetrahedronKey &tid)
Definition: is_mesh.cpp:566
FaceKey insert_face(EdgeKey edge1, EdgeKey edge2, EdgeKey edge3)
Definition: is_mesh.cpp:622
NodeKey get_node(const EdgeKey &eid1, const EdgeKey &eid2)
Definition: is_mesh.cpp:433
iterator find_valid_iterator(key_type k)
Definition: kernel.h:274
NodeKey insert_node(const vec3 &p)
Definition: is_mesh.cpp:606
Definition: kernel.h:80
Definition: key.h:68
FaceKey get_face(const NodeKey &nid1, const NodeKey &nid2, const NodeKey &nid3)
Definition: is_mesh.cpp:475
std::vector< vec3 > get_pos(const SimplexSet< NodeKey > &nids)
Definition: is_mesh.cpp:509
Definition: is_mesh.h:40
EdgeKey insert_edge(NodeKey node1, NodeKey node2)
Definition: is_mesh.cpp:611
Definition: key.h:82
vec3 get_barycenter(const SimplexSet< NodeKey > &nids, bool interface=false)
Definition: is_mesh.cpp:1338
EdgeKey get_edge(const NodeKey &nid1, const NodeKey &nid2)
Definition: is_mesh.cpp:453
Definition: is_mesh_iterator.h:39