CArl
Code Arlequin / C++ implementation
restrict_mesh.cpp
Go to the documentation of this file.
1 /*
2  * restrict_mesh.cpp
3  *
4  * Created on: May 17, 2016
5  * Author: Thiago Milanetto Schlittler
6  */
7 
8 #include "restrict_mesh.h"
9 namespace carl
10 {
11 
12 void Mesh_restriction::BuildRestrictionFromSet(const std::unordered_set<unsigned int> * restricted_mesh_set)
13 {
14  // Intersection and distribution work done already by the stitch algorithm.
15 
16  // Only do the work over a single processor, to avoid communications.
17  if(m_rank == 0)
18  {
19  m_Patch_Elem_indexes.clear();
20  m_Patch_Node_indexes.clear();
22 
23  std::unordered_set<unsigned int >::const_iterator elem_idx_it = restricted_mesh_set->begin();
24  std::unordered_set<unsigned int >::const_iterator elem_idx_it_end = restricted_mesh_set->end();
25 
26  for( ; elem_idx_it != elem_idx_it_end; ++ elem_idx_it)
27  {
28  const libMesh::Elem * elem_to_add = m_Mesh_parent.elem(*elem_idx_it);
29  insert_patch_element(elem_to_add);
30  }
31 
32  this->build_patch_mesh();
33  }
34 }
35 
36 void Mesh_restriction::BuildRestriction(const libMesh::ReplicatedMesh & Coupling_mesh)
37 {
38  bool bDoIntersect = false;
39 
40  // Deque containing the indices of the elements to test
41  std::deque<int> Restriction_Test_Queue;
42 
43  // Unordered set, used to avoid double testing elements
44  unsigned int treated_from_mesh_preallocation = m_Mesh_parent.n_elem();
45  std::unordered_set<int> Treated_From_Mesh;
46 
47  // Only do the work over a single processor, to avoid communications.
48  if(m_rank ==0)
49  {
50  Treated_From_Mesh.reserve(treated_from_mesh_preallocation);
51 
52  std::set<unsigned int> Intersecting_elems;
53 
54  // Index and pointer to element being tested right now
55  unsigned int Tested_idx;
56 
57  // Candidate index
58  unsigned int Candidate_idx;
59 
60  m_Patch_Elem_indexes.clear();
61  m_Patch_Node_indexes.clear();
63 
64  std::set<unsigned int>::iterator it_set_start;
65 
66  libMesh::Mesh::const_element_iterator it_coupling = Coupling_mesh.elements_begin();
67  libMesh::Mesh::const_element_iterator it_coupling_end = Coupling_mesh.elements_end();
68 
69  // Debug vars
70  int nbOfTests = 1;
71  int nbOfPositiveTests = 1;
72 
73  for( ; it_coupling != it_coupling_end; ++it_coupling)
74  {
75  const libMesh::Elem * Query_elem = * it_coupling;
76 
77  Treated_From_Mesh.clear();
78 
79  // Find elements from the original mesh intersecting the coupling element
80  m_Intersection_Test.FindAllIntersection(Query_elem,m_Parent_Point_Locator,Intersecting_elems);
81 
82  libMesh::Elem * First_Restriction_elems = NULL;
83  libMesh::Elem * elem_candidate = NULL;
84  it_set_start = Intersecting_elems.begin();
85 
86  for( ; it_set_start != Intersecting_elems.end(); ++it_set_start)
87  {
88  Treated_From_Mesh.insert(*it_set_start);
89  First_Restriction_elems = m_Mesh_parent.elem(*it_set_start);
90  insert_patch_element(First_Restriction_elems);
91 
92  for(unsigned int iii = 0; iii < First_Restriction_elems->n_neighbors(); ++iii)
93  {
94  elem_candidate = First_Restriction_elems->neighbor(iii);
95  if(elem_candidate != NULL && Treated_From_Mesh.find(elem_candidate->id())==Treated_From_Mesh.end())
96  {
97  Restriction_Test_Queue.push_back(elem_candidate->id());
98  Treated_From_Mesh.insert(elem_candidate->id());
99  }
100  }
101  }
102 
103  while(!Restriction_Test_Queue.empty())
104  {
105  // Extract element from the list
106  Tested_idx = Restriction_Test_Queue[0];
107  Restriction_Test_Queue.pop_front();
108  const libMesh::Elem * Tested_elem = m_Mesh_parent.elem(Tested_idx);
109 
110  // Test it
111  bDoIntersect = m_Intersection_Test.libMesh_exact_do_intersect(Query_elem,Tested_elem);
112  ++nbOfTests;
113 
114  // If it does intersect ...
115  if(bDoIntersect)
116  {
117  ++nbOfPositiveTests;
118 
119  // Add it to the output list ...
120  insert_patch_element(Tested_elem);
121 
122  // ... And add its neighbours (if they weren't tested yet)
123  for(unsigned int iii = 0; iii < Tested_elem->n_neighbors(); ++iii)
124  {
125  elem_candidate = Tested_elem->neighbor(iii);
126  if(elem_candidate != NULL)
127  {
128  Candidate_idx = elem_candidate->id();
129  if(Treated_From_Mesh.find(Candidate_idx)==Treated_From_Mesh.end())
130  {
131  Restriction_Test_Queue.push_back(Candidate_idx);
132  Treated_From_Mesh.insert(Candidate_idx);
133  }
134  }
135  }
136  }
137  }
138  }
139 
140  this->build_patch_mesh();
141 
142  if(m_bPrintDebug)
143  {
144  std::cout << " DEBUG: Restriction search results" << std::endl;
145  std::cout << " -> Nb. of intersections found : " << m_Patch_Elem_indexes.size() << std::endl << std::endl;
146 
147  std::cout << " -> Nb. of mesh elements : " << m_Mesh_parent.n_elem() << std::endl;
148  std::cout << " -> Nb. of Restriction elements : " << m_Patch_Elem_indexes.size() << std::endl;
149  std::cout << " -> Patch elem % : " << 100.*m_Patch_Elem_indexes.size()/m_Mesh_parent.n_elem() << " %" << std::endl << std::endl;
150 
151  std::cout << " -> Nb. of mesh nodes : " << m_Mesh_parent.n_nodes() << std::endl;
152  std::cout << " -> Nb. of patch nodes : " << m_Patch_Node_indexes.size() << std::endl;
153  std::cout << " -> Patch node % : " << 100.*m_Patch_Node_indexes.size()/m_Mesh_parent.n_nodes() << " %" << std::endl << std::endl;
154 
155  std::cout << " -> Nb. of tests : " << nbOfTests << std::endl;
156  std::cout << " -> Nb. of positive tests : " << nbOfPositiveTests << std::endl;
157  std::cout << " -> Positive % : " << 100.*nbOfPositiveTests/nbOfTests << " %" << std::endl << std::endl;
158  }
159  }
160 }
161 
162 void Mesh_restriction::export_restriction_mesh(const std::string & filename_base)
163 {
164  if(m_rank == 0)
165  {
166  std::string filename_mesh = filename_base + ".msh";
167 
168  // Print mesh
169  libMesh::GmshIO output_mesh(m_Mesh_patch);
170  output_mesh.binary() = true;
171  output_mesh.write(filename_mesh);
172 
173  std::string filename_elements = filename_base + "_restrict.dat";
174 
175  std::ofstream elems_out(filename_elements);
176 
177  elems_out << m_elem_map_Patch_to_Parent.size() << std::endl;
178  for(unsigned int iii = 0; iii < m_elem_map_Patch_to_Parent.size(); ++iii)
179  {
180  elems_out << iii << " " << m_elem_map_Patch_to_Parent[iii] << std::endl;
181  }
182 
183  elems_out.close();
184  }
185 }
186 
187 libMesh::ReplicatedMesh & Mesh_restriction::restricted_mesh()
188 {
189  return m_Mesh_patch;
190 }
191 }
libMesh::ReplicatedMesh m_Mesh_patch
Patch mesh.
void BuildRestrictionFromSet(const std::unordered_set< unsigned int > *restricted_mesh_set)
Build the restriction of the parent mesh from a given element set. This version is useful if the inte...
libMesh::ReplicatedMesh & restricted_mesh()
Returns the restricted mesh.
std::unordered_set< unsigned int > m_Patch_Elem_indexes
Set of elements inside the patch.
void insert_patch_element(const libMesh::Elem *Patch_elem)
Insert an parent mesh element inside the patch, updating the data structures.
void export_restriction_mesh(const std::string &filename_base)
Export the restricted mesh to a file.
Intersection_Tools m_Intersection_Test
Intersection search and construction tools.
void BuildRestriction(const libMesh::ReplicatedMesh &Coupling_mesh)
Build the restriction of the parent mesh to the coupling region defined by Coupling_mesh.
bool FindAllIntersection(const libMesh::Elem *Query_elem, std::unique_ptr< libMesh::PointLocatorBase > &point_locator, std::set< unsigned int > &Intersecting_elems)
Find all elements from the mesh intersecting Query_elem, using the mesh's libMesh::PointLocatorBase.
libMesh::ReplicatedMesh & m_Mesh_parent
Parent mesh.
std::unordered_map< unsigned int, std::unordered_set< unsigned int > > m_Patch_Elem_Neighbours
Element neighbour table for the patch.
std::unordered_set< unsigned int > m_Patch_Node_indexes
Set of nodes inside the patch.
std::unique_ptr< libMesh::PointLocatorBase > m_Parent_Point_Locator
Parent mesh point locator.
bool libMesh_exact_do_intersect(const libMesh::Elem *elem_A, const libMesh::Elem *elem_B)
Determinate if two elements intersect.
bool m_bPrintDebug
Print debug information? Default: false.
void build_patch_mesh()
Build a patch mesh from the patch data structures.
std::unordered_map< unsigned int, int > m_elem_map_Patch_to_Parent
Mapping between the patch and parent mesh elements, using the former as keys.
const unsigned int m_rank
Parent mesh processor rank.