LifeV
GraphCutterParMETIS.hpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010, 2011, 2012 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief Class that partitions the graph associated with a mesh.
30  Uses the ParMETIS graph processing library
31 
32  @date 28-11-2012
33  @author Radu Popescu <radu.popescu@epfl.ch>
34  */
35 
36 #ifndef GRAPH_PARTITION_TOOL_PARMETIS_H
37 #define GRAPH_PARTITION_TOOL_PARMETIS_H 1
38 
39 #include <algorithm>
40 #include <boost/shared_ptr.hpp>
41 #include <boost/lexical_cast.hpp>
42 #include <boost/bimap.hpp>
43 #include <Epetra_Comm.h>
44 #include <Teuchos_ParameterList.hpp>
45 
46 #include <lifev/core/LifeV.hpp>
47 #include <lifev/core/mesh/GraphCutterBase.hpp>
48 #include <lifev/core/mesh/GraphUtil.hpp>
49 
50 namespace LifeV
51 {
52 
53 using namespace GraphUtil;
54 
55 //! Class that partitions the graph associated with a mesh (ParMETIS version)
56 /*!
57  @author Radu Popescu <radu.popescu@epfl.ch>
58 
59  This class uses the ParMETIS package to partition the graph associated
60  with a mesh. This class builds the dual graph of the mesh, partitions
61  it according to a set of parameters and the stores the partition
62  in a table (vector of vectors).
63  At the end of the partition process, each vector will contain the
64  GID of the elements in a part.
65 
66  While this class can be used stand-alone, it is used automatically by the
67  MeshPartitionTool class during the mesh partition process.
68  */
69 template<typename MeshType>
70 class GraphCutterParMETIS : public GraphCutterBase<MeshType>
71 {
72 public:
73  //! @name Public Types
74  //@{
77  typedef MeshType mesh_Type;
79 
82  //@}
83 
84  //! @name Constructor & Destructor
85  //! Constructor taking the original mesh, the MPI comm and parameters
86  /*!
87  This constructor can be used to build the object and perform the
88  graph partitioning in one shot.
89 
90  @param mesh The original mesh whose graph this object will partition
91  @param comm The Epetra MPI comm object which contains the processes
92  which participate
93  @param parameters The Teuchos parameter list which contains the
94  partitioning parameters
95  */
97  commPtr_Type& comm,
98  pList_Type& parameters);
99 
100  //! Destructor
101  virtual ~GraphCutterParMETIS() {}
102  //@}
103 
104  //! @name Public methods
105  //@{
106  //! Performs the graph partitioning
107  virtual Int run();
108  //@}
109 
110  //! @name Get Methods
111  //@{
112  //! Get a pointer to one of the partitions
113  virtual const idListPtr_Type& getPart (const UInt i) const
114  {
115  return M_vertexPartition->at (i);
116  }
117  virtual idListPtr_Type& getPart (const UInt i)
118  {
119  return M_vertexPartition->at (i);
120  }
121 
122  //! Return the number of parts
123  virtual const UInt numParts() const
124  {
125  return M_vertexPartition->size();
126  }
127 
128  //! Get the entire partitioned graph, wrapped in a smart pointer
129  virtual const idTablePtr_Type getGraph() const
130  {
131  idTablePtr_Type graph (new idTable_Type (M_vertexPartition->size() ) );
132 
133  for (UInt i = 0; i < M_vertexPartition->size(); ++i)
134  {
135  graph->at (i) = getPart (i);
136  }
137 
138  return graph;
139  }
140 
141  //@}
142 
143 private:
144  //! @name Private methods
145  //@{
146  //! Set values for all the parameters, with default values where needed
147  virtual void setParameters (pList_Type& parameters);
148 
149  //! Perform a flat, non-hierarchical partition
150  Int partitionFlat();
151 
152  //! Perform a hierarchical (2-level) partition
154  //@}
155 
156  // Private copy constructor and assignment operator are disabled
159 
160  //! @name Private Methods
161  //@{
162  //@}
163 
177 };
178 
179 //
180 // IMPLEMENTATION
181 //
182 
183 // =================================
184 // Constructors and Destructor
185 // =================================
186 
187 template<typename MeshType>
189  commPtr_Type& comm,
190  pList_Type& parameters) :
191  M_comm (comm),
192  M_myPID (M_comm->MyPID() ),
194  M_numParts (0),
195  M_parameters(),
196  M_mesh (mesh),
198 {
199  setParameters (parameters);
200 }
201 
202 template<typename MeshType>
203 void GraphCutterParMETIS<MeshType>::setParameters (pList_Type& parameters)
204 {
205  // Here put some default values for the parameters and then import
206  // the user supplied list, overwriting the corresponding parameters
207  M_parameters.set ("num-parts", static_cast<Int> (M_comm->NumProc() ),
208  "The desired number of parts");
209  M_parameters.set<bool> ("hierarchical", false);
210  M_parameters.set ("topology", "1",
211  "The topology of the mesh partition process.");
212 
213  M_parameters.setParameters (parameters);
214 
215  M_hierarchical = M_parameters.get<bool> ("hierarchical");
216  M_topology = stoi (
217  M_parameters.get<std::string> ("topology") );
218  M_numParts = M_parameters.get<Int> ("num-parts");
219 }
220 
221 template<typename MeshType>
223 {
224  // Initialization
225  /*
226  * Sets element parameters (nodes, faces, ridges and number of nodes on each
227  * facet according to the type of mesh element used
228  * (Mesh::ElementShape::S_shape).
229  * Updates M_elementVertices, M_elementFaces, M_elementRidges,
230  * M_facetVertices.
231  */
232  M_elementVertices = MeshType::elementShape_Type::S_numVertices;
233  M_elementFacets = MeshType::elementShape_Type::S_numFacets;
234  M_elementRidges = MeshType::elementShape_Type::S_numRidges;
235  M_facetVertices = MeshType::facetShape_Type::S_numVertices;
236 
237  Int error;
238  if ( (! M_hierarchical) || (M_topology == 1) )
239  {
240  error = partitionFlat();
241  }
242  else
243  {
244  error = partitionHierarchical();
245  }
246 
247  return error;
248 }
249 
250 template<typename MeshType>
252 {
253  // In this case we want to partition the entire graph
254  Int numVertices = M_mesh->numElements();
255 
256  idListPtr_Type vertexList (new idList_Type (numVertices) );
257  for (Int i = 0; i < numVertices; ++i)
258  {
259  vertexList->at (i) = i;
260  }
261 
262  // Call the partitionSubGraph method on the vertexList that was
263  // prepared
264  Teuchos::ParameterList pList;
265  pList.set<Int> ("num-parts", M_numParts);
266  partitionGraphParMETIS (vertexList, * (M_mesh), pList,
267  M_vertexPartition, M_comm);
268 
269  return 0;
270 }
271 
272 template<typename MeshType>
274 {
275  if (M_numProcessors != 1)
276  {
277  if (! M_myPID)
278  {
279  std::cout << "Hierarchical partitioning can only be performed with "
280  << "one MPI process." << std::endl;
281  }
282  return 1;
283  }
284  if (M_numParts % M_topology != 0)
285  {
286  if (! M_myPID)
287  {
288  std::cout << "Hierarchical partitioning can only be performed if "
289  << "the number of mesh parts is a multiple of the"
290  << " topology parameter." << std::endl;
291  }
292  return 2;
293  }
294 
295  // First step is to partition the graph into the number of subdomains
296  Int numSubdomains = M_numParts / M_topology;
297  Int numVertices = M_mesh->numElements();
298 
299  // The vector contains the global IDs of the vertices in the graph
300  idListPtr_Type vertexList (new idList_Type (numVertices) );
301  for (Int i = 0; i < numVertices; ++i)
302  {
303  vertexList->at (i) = i;
304  }
305 
306  idTablePtr_Type tempVertexPartition;
307 
308  /*
309  * After calling partitionSubGraph, tempVertexPartition will contain
310  * numSubdomains vectors with the graph vertices of each subdomain
311  */
312  Teuchos::ParameterList pList;
313  pList.set<Int> ("num-parts", numSubdomains);
314  partitionGraphParMETIS (vertexList, * (M_mesh), pList,
315  tempVertexPartition, M_comm);
316 
317  /*
318  * Step two is to partition each subdomain into the number of sub parts
319  * denoted by the M_topology parameter
320  */
321  pList.set<Int> ("num-parts", M_topology);
322  M_vertexPartition->resize (M_numParts);
323  Int currentPart = 0;
324  for (Int i = 0; i < numSubdomains; ++i)
325  {
326  const idList_Type& currentVertices = * (tempVertexPartition->at (i) );
327  idListPtr_Type subdomainVertexMap (new idList_Type (currentVertices.size() ) );
328  for (size_t k = 0; k < currentVertices.size(); ++k)
329  {
330  subdomainVertexMap->at (k) = currentVertices[k];
331  }
332 
333  idTablePtr_Type subdomainParts;
334 
335  partitionGraphParMETIS (subdomainVertexMap, * (M_mesh),
336  pList, subdomainParts, M_comm);
337 
338  for (Int j = 0; j < M_topology; ++j)
339  {
340  M_vertexPartition->at (currentPart++) = subdomainParts->at (j);
341  }
342  }
343 
344  return 0;
345 }
346 
347 } // Namespace LifeV
348 
349 #endif // GRAPH_PARTITION_TOOL_PARMETIS_H
Int partitionHierarchical()
Perform a hierarchical (2-level) partition.
GraphCutterParMETIS(const GraphCutterParMETIS &)
Graph cutter base class (abstract)
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
virtual void setParameters(pList_Type &parameters)
Set values for all the parameters, with default values where needed.
void updateInverseJacobian(const UInt &iQuadPt)
virtual const idTablePtr_Type getGraph() const
Get the entire partitioned graph, wrapped in a smart pointer.
virtual const UInt numParts() const
Return the number of parts.
GraphCutterParMETIS & operator=(const GraphCutterParMETIS &)
std::vector< LifeV::Int > idList_Type
Definition: GraphUtil.hpp:60
GraphCutterParMETIS(meshPtr_Type &mesh, commPtr_Type &comm, pList_Type &parameters)
virtual ~GraphCutterParMETIS()
Destructor.
Class that partitions the graph associated with a mesh (ParMETIS version)
boost::bimap< UInt, UInt > biMap_Type
biMap_Type::value_type biMapValue_Type
virtual Int run()
Performs the graph partitioning.
std::shared_ptr< idTable_Type > idTablePtr_Type
Definition: GraphUtil.hpp:63
virtual idListPtr_Type & getPart(const UInt i)
Int partitionFlat()
Perform a flat, non-hierarchical partition.
std::shared_ptr< mesh_Type > meshPtr_Type
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
std::shared_ptr< Epetra_Comm > commPtr_Type
std::shared_ptr< idList_Type > idListPtr_Type
Definition: GraphUtil.hpp:61
Teuchos::ParameterList pList_Type
virtual const idListPtr_Type & getPart(const UInt i) const
Get a pointer to one of the partitions.