CArl
Code Arlequin / C++ implementation
mesh_intersection_methods.cpp
Go to the documentation of this file.
2 
3 namespace carl
4 {
5 
6 void Mesh_Intersection::triangulate_intersection(const std::set<libMesh::Point> & input_points)
7 {
9 
10  for(std::set<libMesh::Point>::const_iterator it_set = input_points.begin();
11  it_set != input_points.end();
12  ++it_set)
13  {
14  libMesh::Point dummy = *it_set;
15  m_libMesh_PolyhedronMesh.add_point(*it_set);
16  }
17 
18  switch (m_MeshingMethod)
19  {
21  {
22  libMesh::TetGenMeshInterface temp_tetgen_interface(m_libMesh_PolyhedronMesh);
23  temp_tetgen_interface.triangulate_pointset();
24  break;
25  }
27  {
28  // Clear CGAL's mesh
29  m_CGAL_PolyhedronMesh.clear();
30 
31  // This is a superfluous extra point conversion:
32  // (CGAL Exact -> CGAL Inexact -> LibMesh -> CGAL Inexact)
33  // But changing this would need a re-structuring of the code (TODO !)
34  Point_3 dummy_CGAL_point;
35  const libMesh::Point * dummy_libMesh_point;
36  for(int iii = 0; iii < input_points.size(); ++iii)
37  {
38  dummy_libMesh_point = &m_libMesh_PolyhedronMesh.point(iii);
39  dummy_CGAL_point = Point_3( (*dummy_libMesh_point)(0),(*dummy_libMesh_point)(1),(*dummy_libMesh_point)(2));
40 
41  // Insert vertex and save the corresponding
42  Vertex_handle_3 dummy_vertex_handle = m_CGAL_PolyhedronMesh.insert(dummy_CGAL_point);
43  dummy_vertex_handle->info().ExtIndex = iii;
44  }
45 
46  // At this point, CGAL generated the mesh, now we have to convert it to libMesh
47  unsigned int dummy_vertex_idx = 0;
48  for( Finite_cells_iterator_3 cell_it = m_CGAL_PolyhedronMesh.finite_cells_begin();
49  cell_it != m_CGAL_PolyhedronMesh.finite_cells_end();
50  ++cell_it)
51  {
52  libMesh::Elem * elem_pointer = m_libMesh_PolyhedronMesh.add_elem(new libMesh::Tet4);
53  for(int iii = 0; iii < 4; ++iii)
54  {
55  dummy_vertex_idx = cell_it->vertex(iii)->info().ExtIndex;
56  elem_pointer->set_node(iii) = &(m_libMesh_PolyhedronMesh.node(dummy_vertex_idx));
57  }
58  }
59  m_libMesh_PolyhedronMesh.prepare_for_use();
60 
61  break;
62  }
63  }
64 }
65 
67 {
68  // Test which elements must be added, and insert their vertices
69  libMesh::ReplicatedMesh::element_iterator it_poly_mesh = m_libMesh_PolyhedronMesh.elements_begin();
70 
71  for( ; it_poly_mesh != m_libMesh_PolyhedronMesh.elements_end();
72  ++it_poly_mesh)
73  {
74  libMesh::Elem * poly_elem = * it_poly_mesh;
75 
76  if(std::abs(poly_elem->volume()) > m_vol_tol)
77  {
78  // Add a new element!
79  libMesh::Elem * mesh_elem = m_libMesh_Mesh.add_elem(new libMesh::Tet4);
80 
81  // -> First, add the nodes
82  for(unsigned int iii = 0; iii < 4; ++iii)
83  {
84  convert_to_discrete(poly_elem->point(iii),m_dummy_discrete_point);
85 
87  {
88  // New vertex! Add it to the mesh
89 
91  m_libMesh_Mesh.add_point(poly_elem->point(iii),m_nb_of_vertices);
92  mesh_elem->set_node(iii) = m_libMesh_Mesh.node_ptr(m_nb_of_vertices);
94  }
95 
96  // Associate vertex to the new element
97  mesh_elem->set_node(iii) = m_libMesh_Mesh.node_ptr(m_discrete_vertices[m_dummy_discrete_point]);
98  }
99  // Increase the number of elements
101  }
102  }
103 }
104 
105 void Mesh_Intersection::update_intersection_pairs(unsigned int elem_idx_A, unsigned int elem_idx_B, unsigned int inter_id)
106 {
107  m_intersection_pairs[inter_id] = std::make_pair(elem_idx_A, elem_idx_B);
108 }
109 
110 void Mesh_Intersection::update_intersection_element_range(unsigned int range_start, unsigned int range_end, unsigned int inter_id)
111 {
112  m_intersection_element_range[inter_id] = std::make_pair(range_start, range_end);
113 }
114 
115 const libMesh::ReplicatedMesh & Mesh_Intersection::mesh()
116 {
117  return m_libMesh_Mesh;
118 }
119 
121 {
122  return m_Grid_MinPoint;
123 }
124 
126 {
127  return m_Grid_MaxPoint;
128 }
129 
131 {
132  return m_eps;
133 }
134 
136 {
137  return m_vol_tol;
138 }
139 
140 std::vector<long> & Mesh_Intersection::grid_sizes()
141 {
142  return m_GridN;
143 }
144 
146 {
147  return m_GridN_min;
148 }
149 
151 {
152  m_libMesh_Mesh.clear();
153  m_discrete_vertices.clear();
154  m_bMeshFinalized = false;
155  m_intersection_pairs.clear();
156  m_intersection_couplings.clear();
159  m_nb_of_elements = 0 ;
160  m_nb_of_vertices = 0 ;
161  m_nb_of_points = 0 ;
162 }
163 
164 void Mesh_Intersection::preallocate_grid( int map_preallocation )
165 {
166 // m_Grid_to_mesh_vertex_idx.reserve(map_preallocation);
167  m_discrete_vertices.reserve(map_preallocation);
168 }
169 
170 void Mesh_Intersection::set_grid_constraints(const libMesh::Mesh & mesh_A, const libMesh::Mesh & mesh_B, double vol_tol)
171 {
172  libMesh::MeshTools::BoundingBox bbox_A = libMesh::MeshTools::bounding_box(mesh_A);
173  libMesh::MeshTools::BoundingBox bbox_B = libMesh::MeshTools::bounding_box(mesh_B);
174 
175  // Just to be sure, test if the bboxes intersect!
176  homemade_assert_msg(bbox_A.intersect(bbox_B),"Meshes' bounding boxes do not intersect!\n");
177 
178  // Set the (future) intersection bbox corners
179  std::vector<double> eps_candidates(3,0);
180  for(unsigned int iii = 0; iii < 3; ++iii)
181  {
182  m_Grid_MinPoint(iii) = std::max(bbox_A.min()(iii),bbox_B.min()(iii));
183  m_Grid_MaxPoint(iii) = std::min(bbox_A.max()(iii),bbox_B.max()(iii));
184  eps_candidates[iii] = (m_Grid_MaxPoint(iii) - m_Grid_MinPoint(iii))/m_GridN_min;
185  }
186 
187  m_eps = *std::min_element(eps_candidates.begin(),eps_candidates.end());
188 
189  for(unsigned int iii = 0; iii < 3; ++iii)
190  {
191  m_Grid_MinPoint(iii) -= 2*m_eps;
192  m_Grid_MaxPoint(iii) += 2*m_eps;
193  }
194 
195  if( vol_tol < 0 )
196  {
197  // Grossily estimate the volume of A's and B's elements using the bbox
198  double grid_volume = (m_Grid_MaxPoint(0) - m_Grid_MinPoint(0)) *
199  (m_Grid_MaxPoint(1) - m_Grid_MinPoint(1)) *
201 
202 
203  double fraction_vol_A = (bbox_A.max()(0) - bbox_A.min()(0)) *
204  (bbox_A.max()(1) - bbox_A.min()(1)) *
205  (bbox_A.max()(2) - bbox_A.min()(2)) /
206  grid_volume;
207 
208  double fraction_vol_B = (bbox_B.max()(0) - bbox_B.min()(0)) *
209  (bbox_B.max()(1) - bbox_B.min()(1)) *
210  (bbox_B.max()(2) - bbox_B.min()(2)) /
211  grid_volume;
212 
213  unsigned int est_elem = std::max(fraction_vol_A * mesh_A.n_elem(),fraction_vol_B * mesh_B.n_elem());
214 
215  m_vol_tol = 1E-6 * grid_volume / est_elem;
216  }
217  else
218  {
219  m_vol_tol = vol_tol;
220  }
221 
222  for(unsigned int iii = 0; iii < 3; ++iii)
223  {
224  m_GridN[iii] = (m_Grid_MaxPoint(iii) - m_Grid_MinPoint(iii)) / m_eps + 1;
225  }
226 
227  if(m_bPrintDebug)
228  {
229  std::cout << " DEBUG: discrete grid" << std::endl;
230  std::cout << " -> eps : " << m_eps << std::endl;
231  std::cout << " -> volume : " << m_vol_tol << std::endl;
232  std::cout << " -> Grid dimensions : " << m_GridN[0] << " " << m_GridN[1] << " " << m_GridN[2] << " " << std::endl << std::endl;
233  }
234 }
235 
236 void Mesh_Intersection::increase_intersection_mesh( const std::set<libMesh::Point> & input_points,
237  unsigned int elem_idx_A,
238  unsigned int elem_idx_B,
239  unsigned int elem_idx_C)
240 {
241  m_bMeshFinalized = false;
242  unsigned int intersection_range_start = m_nb_of_elements;
243 
244  // First, triangulate the point set!
245  triangulate_intersection(input_points);
246 
247  // Second, add the points to the grid-to-mesh map and update the intersection mesh,
248  // taking into account if the associated elements are big enough.
250 
251  // Third, update the intersection pairs, if needed
252  unsigned int intersection_range_end = m_nb_of_elements;
253  if(intersection_range_end != intersection_range_start)
254  {
255  update_intersection_pairs(elem_idx_A, elem_idx_B,m_nb_of_intersections);
257  update_intersection_element_range(intersection_range_start,intersection_range_end,m_nb_of_intersections);
259  }
260 }
261 
262 void Mesh_Intersection::export_intersection_data(const std::string & filename_base, const std::string & mesh_format)
263 {
264  homemade_assert_msg(m_bMeshFinalized, "Mesh not prepared for use yet!\n");
265 
266  // Set the filenames depending on the processor rank
267  std::string mesh_file_out = filename_base + mesh_format;
268  std::string table_file_out = filename_base + "_inter_table.dat";
269 
270  // Print the mesh
271  libMesh::NameBasedIO output_mesh(m_libMesh_Mesh);
272  output_mesh.write(mesh_file_out);
273 
274  // Print the intersection table
275  std::ofstream table_out(table_file_out);
276  unsigned int nb_of_inter_elements = 0;
277  table_out << m_nb_of_intersections << " " << m_libMesh_Mesh.n_elem() << " " << m_libMesh_Mesh.n_nodes() << std::endl;
278 
279  for(unsigned int iii = 0; iii < m_nb_of_intersections; ++iii)
280  {
281  nb_of_inter_elements = m_intersection_element_range[iii].second
282  - m_intersection_element_range[iii].first;
283  table_out << iii << " " << m_intersection_pairs[iii].first << " "
284  << m_intersection_pairs[iii].second << " "
285  << nb_of_inter_elements;
286  for(unsigned int jjj = 0; jjj < nb_of_inter_elements; ++jjj)
287  {
288  table_out << " " << m_intersection_element_range[iii].first + jjj;
289  }
290  table_out << std::endl;
291  }
292  table_out.close();
293 }
294 
296 {
297  if(m_bPrintDebug)
298  {
299  // Print information about the number of collisions
300  size_t collisions = 0;
301  for (size_t bucket = 0; bucket != m_discrete_vertices.bucket_count(); ++bucket)
302  {
303  if (m_discrete_vertices.bucket_size(bucket) > 1)
304  {
305  collisions += m_discrete_vertices.bucket_size(bucket) - 1;
306  }
307  }
308 
309  std::cout << " DEBUG: discrete grid hash collisions" << std::endl;
310  std::cout << " -> Nb. of collisions / size : " << collisions << " / " << m_discrete_vertices.size()
311  << " (" << 100.*collisions/m_discrete_vertices.size() << "%)" << std::endl << std::endl;
312  }
313 
314  m_libMesh_Mesh.prepare_for_use();
315  m_bMeshFinalized = true;
316 }
317 
319 {
320  double volume = 0;
321 
322  homemade_assert_msg(m_bMeshFinalized,"Intersection mesh was not prepared for use!\n");
323 
324  for(libMesh::ReplicatedMesh::element_iterator it_elem = m_libMesh_Mesh.elements_begin();
325  it_elem != m_libMesh_Mesh.elements_end();
326  ++it_elem)
327  {
328  const libMesh::Elem * elem = * it_elem;
329  volume += elem->volume();
330  }
331 
332  return volume;
333 }
334 
335 double Mesh_Intersection::get_intersection_volume(std::set<libMesh::Point> & input_points)
336 {
337  double volume = 0;
338 
339  triangulate_intersection(input_points);
340 
341  for(libMesh::ReplicatedMesh::element_iterator it_elem = m_libMesh_PolyhedronMesh.elements_begin();
342  it_elem != m_libMesh_PolyhedronMesh.elements_end();
343  ++it_elem)
344  {
345  const libMesh::Elem * elem = * it_elem;
346  volume += elem->volume();
347  }
348 
349  return volume;
350 }
351 
352 void Mesh_Intersection::convert_to_discrete(const libMesh::Point& iPoint, std::vector<long>& oPoint)
353 {
354  oPoint[0] = lround( (iPoint(0) - m_Grid_MinPoint(0) )/m_eps);
355  oPoint[1] = lround( (iPoint(1) - m_Grid_MinPoint(1) )/m_eps);
356  oPoint[2] = lround( (iPoint(2) - m_Grid_MinPoint(2) )/m_eps);
357 }
358 }
double get_total_volume()
Calculate the intersection mesh's total volume.
libMesh::Point & min_point()
Returns the minimal point of the discrete grid.
unsigned int m_nb_of_points
(Unused!)
libMesh::ReplicatedMesh & m_libMesh_Mesh
Address of the intersection mesh.
void update_intersection_mesh()
Update the intersection mesh with the current polyhedron mesh data.
libMesh::Point & max_point()
Returns the maximum point of the discrete grid.
void convert_to_discrete(const libMesh::Point &iPoint, std::vector< long > &oPoint)
Convert a real valued point to a discrete point.
const libMesh::ReplicatedMesh & mesh()
Returns the address of the intersection mesh.
std::unordered_map< std::vector< long >, unsigned int, PointHash_3D, PointHash_3D_Equal > m_discrete_vertices
Unordered map (or hash) for the discrete points (key).
long grid_min_size()
Returns the minimum discrete grid size.
void increase_intersection_mesh(const std::set< libMesh::Point > &input_points, unsigned int elem_idx_A, unsigned int elem_idx_B, unsigned int elem_idx_C)
Increase the intersection mesh with the current polyhedron mesh and update its data structures...
void export_intersection_data(const std::string &filename_base, const std::string &mesh_format=std::string(".e"))
Export both the intersection mesh its data structures.
std::unordered_map< unsigned int, std::pair< unsigned int, unsigned int > > m_intersection_pairs
Unordered map containing the element pair associated to each intersection (key).
Kernel::Point_3 Point_3
IntersectionMeshingMethod m_MeshingMethod
Choice of meshing algorithm.
libMesh::Point m_Grid_MinPoint
Minimal point of the discrete grid.
void set_grid_constraints(const libMesh::Mesh &mesh_A, const libMesh::Mesh &mesh_B, double vol_tol=-1)
Set the boundaries of the discrete points grid, taking into account the geometry of meshes mesh_A and...
std::unordered_map< unsigned int, unsigned int > m_intersection_couplings
Unordered map associating each intersection (key) to a coupling element (useless!) ...
double eps()
Returns the discrete grid step.
void triangulate_intersection(const std::set< libMesh::Point > &input_points)
Triangulate an intersection defined by a set of libMesh::Points, using either CGAL or Tetgen...
DT_3::Vertex_handle Vertex_handle_3
unsigned int m_nb_of_vertices
Number of vertices of the intersection mesh.
std::unordered_map< unsigned int, std::pair< unsigned int, unsigned int > > m_intersection_element_range
Unordered map associating each intersection (key) to a range of elements in the intersection mesh...
bool m_bPrintDebug
Print debug information? Default: false.
double min_vol()
Returns the minimal polyhedron volume.
double m_eps
Precision of the discrete point grid.
bool m_bMeshFinalized
Boolean controlling if the intersection mesh was finished or not.
void initialize()
Initialize the data structures.
std::vector< long > & grid_sizes()
Returns the discrete grid sizes.
std::vector< long > m_dummy_discrete_point
libMesh::Mesh m_libMesh_PolyhedronMesh
libMesh Mesh containing the tetrahedrization of an intersection polyhedron (the polyhedron mesh)...
double get_intersection_volume(std::set< libMesh::Point > &input_points)
Calculate the volume of an polyhedron defined by the point set.
void preallocate_grid(int map_preallocation)
Preallocate the discrete points grid.
void update_intersection_pairs(unsigned int elem_idx_A, unsigned int elem_idx_B, unsigned int inter_id)
Update the intersection pair map with a new pair associated to the intersection no. inter_id.
#define homemade_assert_msg(asserted, msg)
Definition: common_header.h:63
double m_vol_tol
Minimal volume for the intersection polyhedrons.
long m_GridN_min
Minimal number of integers over each dimension of the discrete grid.
DT_3 m_CGAL_PolyhedronMesh
Auxiliary CGAL mesh, used if CGAL is chosen for the tetrahedrization.
void prepare_for_use()
Prepare the intersection mesh for use.
std::vector< long > m_GridN
Dimensions of the discrete point grid.
DT_3::Finite_cells_iterator Finite_cells_iterator_3
unsigned int m_nb_of_elements
Number of elements of the intersection mesh.
void update_intersection_element_range(unsigned int range_start, unsigned int range_end, unsigned int inter_id)
Update the intersection element range map with a new range associated to the intersection no...
libMesh::Point m_Grid_MaxPoint
Maximum point of the discrete grid.