LifeV
MeshColoring.cpp
Go to the documentation of this file.
1 #include <lifev/core/mesh/MeshColoring.hpp>
2 
3 
4 namespace LifeV
5 {
6 
7 MeshColoring::MeshColoring(const commPtr_Type& communicator):
8  M_comm(communicator)
9 {
10 }
11 
13 {
14 }
15 
16 void MeshColoring::setMesh ( const meshPtr_Type& local_mesh )
17 {
18  M_mesh = local_mesh;
19 }
20 
22 {
23  int numVertices = M_mesh->numGlobalVertices();
24  int numVolumes = M_mesh->numGlobalElements();
25  UInt numberLocalDof = 4;
26 
27  M_nodesToVolumes.resize(numVertices);
28  M_volumesToNodes.resize(numVolumes);
29  M_numNeighbors.resize(numVertices);
30 
31  for ( int i = 0; i < M_mesh->numElements(); ++i ) // local number of elements
32  {
33  M_volumesToNodes[M_mesh->element(i).id()].resize(4);
34  for ( int j = 0; j < 4; ++j )
35  {
36  M_volumesToNodes[M_mesh->element(i).id()][j] = M_mesh->element(i).point(j).id();
37  M_nodesToVolumes[M_mesh->element(i).point(j).id()].push_back(M_mesh->element(i).id());
38  }
39  }
40 
41  for ( int i = 0; i < numVertices; ++i )
42  {
43  M_numNeighbors[i] = M_nodesToVolumes[i].size();
44  }
45 
46  std::vector<UInt>::iterator indexMaxNumNeighbors = std::max_element(M_numNeighbors.begin(), M_numNeighbors.end() );
47  M_indexNodeMaxNumNeighbors = std::distance(M_numNeighbors.begin(), indexMaxNumNeighbors);
48  M_maxNumNeighbors = M_numNeighbors[M_indexNodeMaxNumNeighbors];
50 
51  // debug info
52  // std::cout << "\nNode with most elements connected is " << M_indexMaxNumNeighbors << " with " << M_maxNumNeighbors << " elements\n";
53 
54  // building element - neighbors map (element i has neighbors element j k z for example)
55  M_volumesToVolumes.resize(numVolumes);
56  for ( int i = 0; i < M_mesh->numElements(); ++i ) // local number of elements
57  {
58  for ( int j = 0; j < 4; ++j )
59  {
60  std::vector<UInt> volumes_tmp = M_nodesToVolumes[M_mesh->element(i).point(j).id()];
61  for ( int k = 0; k < volumes_tmp.size(); ++k )
62  {
63  M_volumesToVolumes[M_mesh->element(i).id()].push_back( volumes_tmp[k] );
64  }
65  }
66  std::sort( M_volumesToVolumes[M_mesh->element(i).id()].begin(), M_volumesToVolumes[M_mesh->element(i).id()].end() );
67  M_volumesToVolumes[M_mesh->element(i).id()].erase( unique( M_volumesToVolumes[M_mesh->element(i).id()].begin(),
68  M_volumesToVolumes[M_mesh->element(i).id()].end() ),
69  M_volumesToVolumes[M_mesh->element(i).id()].end() );
70  M_volumesToVolumes[M_mesh->element(i).id()].erase(std::remove(M_volumesToVolumes[M_mesh->element(i).id()].begin(),
71  M_volumesToVolumes[M_mesh->element(i).id()].end(),
72  M_mesh->element(i).id()),
73  M_volumesToVolumes[M_mesh->element(i).id()].end());
74  }
75 
76  // build distributed map for exporter
77  std::vector<int> id_elem_scalar;
78 
79  for ( int i = 0; i < M_mesh->numVolumes(); ++i )
80  {
81  id_elem_scalar.push_back ( M_mesh->element(i).id() );
82  }
83 
84  int* pointerToDofs_scalar (0);
85  pointerToDofs_scalar = &id_elem_scalar[0];
86  std::shared_ptr<MapEpetra> map_scalar ( new MapEpetra ( -1, static_cast<int> (id_elem_scalar.size() ), pointerToDofs_scalar, M_comm ) );
87 
88  M_vectorColors.reset ( new vector_Type ( *map_scalar, Unique ) );
89  M_vectorColors->zero();
90 
91 }
92 
94 {
95  M_colors.resize ( M_mesh->numGlobalElements() );
96  std::for_each ( M_colors.begin(), M_colors.end(), [] (int&d) { d = -1.0;} );
97 
98  for ( int j = 0; j < M_numColors; ++j )
99  {
100  M_colors[ M_nodesToVolumes[M_indexNodeMaxNumNeighbors][j] ] = j;
101  }
102 
103  std::vector<int> all_colors;
104  all_colors.resize(M_numColors);
105  std::iota (std::begin(all_colors), std::end(all_colors), 0);
106 
107  for ( int k = 0; k < M_mesh->numElements(); ++k ) // local number of elements
108  {
109  if ( M_colors[ M_mesh->element(k).id() ] == -1.0 )
110  {
111  std::vector<UInt> neigbors = M_volumesToVolumes[M_mesh->element(k).id()];
112  std::vector<int> my_colors;
113  my_colors.resize(neigbors.size());
114  for ( int z = 0; z < neigbors.size(); ++z )
115  {
116  my_colors[z] = M_colors[neigbors[z]];
117  }
118 
119  std::vector<int> vector_diff;
120  std::sort (my_colors.begin(),my_colors.end());
121  std::set_difference (all_colors.begin(), all_colors.end(),
122  my_colors.begin(), my_colors.end(),
123  std::inserter(vector_diff, vector_diff.begin()) );
124 
125  if ( vector_diff.size() == 0 )
126  {
127  M_numColors = M_numColors + 1;
128  M_colors[M_mesh->element(k).id()] = M_numColors-1;
129  all_colors.resize(M_numColors);
130  std::iota (std::begin(all_colors), std::end(all_colors), 0);
131  }
132  else
133  {
134  std::vector<int>::iterator result = std::min_element(std::begin(vector_diff), std::end(vector_diff));
135  M_colors[M_mesh->element(k).id()] = vector_diff[std::distance(std::begin(vector_diff), result)];
136  }
137  }
138  }
139 
140  // fill epetra vector with colors
141  for ( int i = 0; i < M_vectorColors->epetraVector().MyLength(); ++i )
142  {
143  (*M_vectorColors)[M_vectorColors->blockMap().GID(i)] = M_colors[M_vectorColors->blockMap().GID(i)];
144  }
146 }
147 
149 {
150  M_colorsForAssembly.resize(M_numColors);
151 
152  for ( int i = 0; i < M_vectorColors->epetraVector().MyLength(); ++i )
153  {
154  M_colorsForAssembly[ (*M_vectorColors)[M_vectorColors->blockMap().GID(i)] ].push_back(i);
155  }
156 }
157 
158 
160 {
161  for ( int i = 0; i < M_volumesToVolumes.size(); ++i )
162  {
163  std::cout << "\nElement " << i << " attached to elements " << std::flush;
164  for ( int j = 0; j < M_volumesToVolumes[i].size(); ++j )
165  {
166  std::cout << M_volumesToVolumes[i][j] << " ";
167  }
168  }
169  std::cout << "\n";
170 }
171 
173 {
174  for ( int i = 0; i < M_nodesToVolumes.size(); ++i )
175  {
176  std::cout << "\nNode " << i << " attached to elements " << std::flush;
177  for ( int j = 0; j < M_nodesToVolumes[i].size(); ++j )
178  {
179  std::cout << M_nodesToVolumes[i][j] << " ";
180  }
181  }
182  std::cout << "\n";
183 }
184 
186 {
187  for ( int i = 0; i < M_volumesToNodes.size(); ++i )
188  {
189  std::cout << "\nElement " << i << " has vertices " << std::flush;
190  for ( int j = 0; j < M_volumesToNodes[i].size(); ++j )
191  {
192  std::cout << M_volumesToNodes[i][j] << " ";
193  }
194  }
195  std::cout << "\n";
196 }
197 
199 {
200  for ( int i = 0; i < M_numNeighbors.size(); ++i )
201  {
202  std::cout << "\nVertex " << i << " touches " << M_numNeighbors[i] << " elements " << std::endl;
203  }
204 }
205 
207 {
208  for ( int i = 0; i < M_vectorColors->epetraVector().MyLength(); ++i )
209  {
210  std::cout << "\nElement " << M_vectorColors->blockMap().GID(i)
211  << " on proc ID " << M_comm->MyPID()
212  << " has color " << M_colors[M_vectorColors->blockMap().GID(i)]
213  << std::endl;
214  }
215  std::cout << "\n";
216 }
217 
219 {
220  int check = 0;
221 
222  for ( int k = 0; k < M_mesh->numVertices(); ++k ) // local number of vertices
223  {
224  std::vector<UInt> neigbors = M_nodesToVolumes[M_mesh->point(k).id()];
225  std::vector<int> colors_neighbors;
226  for ( int z = 0; z < neigbors.size(); ++z )
227  {
228  colors_neighbors.push_back(M_colors[neigbors[z]]);
229  }
230  // put in the colors_neighbors also the color of element k. Then check if size(unique(colors_neighbors))) is
231  // equal to size colors_neighbors. If not there is an error.
232  int size_initial = colors_neighbors.size();
233  std::sort( colors_neighbors.begin(), colors_neighbors.end() );
234  colors_neighbors.erase( unique( colors_neighbors.begin(), colors_neighbors.end() ), colors_neighbors.end() );
235  int size_after = colors_neighbors.size();
236 
237  if ( size_after != size_initial )
238  {
239  check++;
240  std::cout << "\nInitial = " << size_initial << ", after = " << size_after << std::endl;
241  std::cout << "\nError in coloring around vertex " << M_mesh->point(k).id() << std::endl;
242  }
243  }
244  return check;
245 }
246 
248 {
249  for ( int i = 0; i < M_colorsForAssembly.size(); ++i )
250  {
251  if ( M_colorsForAssembly[i].size() > 0 )
252  {
253  std::cout << "\nColor " << i << " has elements with LID " << std::flush;
254  for ( int j = 0; j < M_colorsForAssembly[i].size(); ++j )
255  {
256  std::cout << M_colorsForAssembly[i][j] << " ";
257  }
258  std::cout << std::endl;
259  }
260  }
261  std::cout << "\n";
262 }
263 
265 {
266  // Number of colors per process
267  std::cout << "\nOn proc " << M_comm->MyPID() << " there are " << M_numColors << " colors\n";
268 
269  M_comm->Barrier();
270 
271  for ( int k = 0; k < M_comm->NumProc(); ++k )
272  {
273  if ( M_comm->MyPID() == k )
274  {
275  for ( int i = 0; i < M_colorsForAssembly.size(); ++i )
276  {
277  if ( M_colorsForAssembly[i].size() > 0 )
278  {
279  std::cout << "\nColor " << i << " has elements " << M_colorsForAssembly[i].size() << std::endl;
280  }
281  }
282  }
283  }
284 
285 }
286 
287 
288 }
std::shared_ptr< comm_Type > commPtr_Type
int performCheck()
Check if colors have been assigned correctly.
void printInfo()
Info about coloring.
void printVolumesToNodes()
Print volume to node connections.
void colorsForAssembly()
Vector of colors for the assembly.
void printNodesToVolumes()
Print node to volume connections.
void printColorsForAssembly()
Vector of colors used in the assembly.
void updateInverseJacobian(const UInt &iQuadPt)
void printVolumesToVolumes()
Print volume to volume connections.
~MeshColoring()
Destructor.
void setMesh(const meshPtr_Type &local_mesh)
Set the mesh.
MeshColoring(const commPtr_Type &communicator)
Empty Constructor.
Definition: MeshColoring.cpp:7
std::shared_ptr< mesh_Type > meshPtr_Type
void setup()
Initial setup of the class.
void colorMesh()
Perform the coloring of the mesh.
void printColors()
Print vector of colors.
void printNumNeighbors()
Print number of element neighbors per node.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
MeshData - class for coloring mesh.