COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Partitioner.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #include <set>
8 
9 #include "common/Builder.hpp"
10 #include "common/PropertyList.hpp"
11 #include "common/OptionList.hpp"
12 #include "common/OptionT.hpp"
14 #include "common/PE/Comm.hpp"
15 #include "common/PE/debug.hpp"
16 #include "common/Log.hpp"
17 #include "common/Map.hpp"
18 
19 #include "mesh/Dictionary.hpp"
21 
22 namespace cf3 {
23 namespace mesh {
24 namespace zoltan {
25 
26  using namespace common;
27  using namespace common::PE;
28 
29 #define RANK "[" << Comm::instance().rank() << "] "
30 
32 
34 
36 
37 Partitioner::Partitioner ( const std::string& name ) :
38  MeshPartitioner(name),
39  m_partitioned(false)
40 {
41 
42  options().add("graph_package", "PHG")
43  .description("External library zoltan will use for graph partitioning")
44  .pretty_name("Graph Package")
45  .mark_basic();
46 
47  options().add("debug_level", 0u)
48  .description("Internal zoltan debug level (0 to 10)")
49  .pretty_name("Debug Level");
50 
51  float version;
52  int error_code = Zoltan_Initialize(Core::instance().argc(),Core::instance().argv(),&version);
53  cf3_assert_desc("Could not initialize zoltan", error_code == ZOLTAN_OK);
54  m_zoltan_version = version;
55 
56  properties().add("Zoltan_version",m_zoltan_version);
57 }
58 
60 
62 {
63  if (m_partitioned)
64  {
65  Zoltan::LB_Free_Part(&importGlobalIds, &importLocalIds, &importProcs, &importToPart);
66  Zoltan::LB_Free_Part(&exportGlobalIds, &exportLocalIds, &exportProcs, &exportToPart);
67  }
68 
69  // m_zz is deleted automatically by shared_ptr
70 }
71 
73 {
74  cf3_assert( Comm::instance().is_initialized() );
75 
76  if ( is_null(m_zz) ) // create it
77  {
78  m_zz.reset( new Zoltan( Comm::instance().communicator() ) );
79  cf3_assert (m_zz != nullptr);
80  }
81 
82  return *m_zz;
83 }
84 
86 
88 {
89  CFdebug.setFilterRankZero(false);
90 
91  m_partitioned = true;
93 
97 
98  if(numExport < 0)
99  {
100  throw common::ParallelError(FromHere(), "Partitioning failed");
101  }
102 
103  Uint comp; Uint loc_idx; bool found;
104  for (int i=0; i<numExport; ++i)
105  {
106  boost::tie(comp,loc_idx) = location_idx(exportGlobalIds[i]);
107  if (comp == 0) // if is node
108  {
109  m_nodes_to_export[exportToPart[i]].push_back(loc_idx);
110  }
111  else // if is element
112  {
113  m_elements_to_export[exportToPart[i]][comp-1].push_back(loc_idx);
114  }
115  }
116 
117  // Import should not have been assigned
118  // see line below: zoltan_handle().Set_Param( "RETURN_LISTS", "EXPORT");
119  cf3_assert((int)numImport<=0);
120 
121  CFdebug.setFilterRankZero(true);
122 
123 }
124 
126 
128 {
130  zoltan_handle().Set_Param( "DEBUG_LEVEL", to_str( options()["debug_level"].value<Uint>() ));
131  // 0 Quiet mode; no output unless an error or warning is produced.
132  // 1 Values of all parameters set by Zoltan_Set_Param and used by zoltan.
133  // 2 Timing information for zoltan's main routines.
134  // 3 Timing information within zoltan's algorithms (support by algorithms is optional).
135  // 4
136  // 5 Trace information (enter/exit) for major zoltan interface routines (printed by the processor specified by the DEBUG_PROCESSOR parameter).
137  // 6 Trace information (enter/exit) for major zoltan interface routines (printed by all processors).
138  // 7 More detailed trace information in major zoltan interface routines.
139  // 8 List of objects to be imported to and exported from each processor. [1]
140  // 9
141  // 10 Maximum debug output; may include algorithm-specific output. [1]
142  //
143  // [1] Output may be serialized; that is, one processor may have to complete its output before the next processor
144  // is allowed to begin its output. This serialization is not scalable and can significantly increase execution
145  // time on large number of processors.
146 
147 
148  zoltan_handle().Set_Param( "LB_METHOD", "HYPERGRAPH");
149  // The load-balancing algorithm used by zoltan is specified by this parameter. Valid values are
150  // BLOCK (for block partitioning),
151  // RANDOM (for random partitioning),
152  // RCB (for recursive coordinate bisection),
153  // RIB (for recursive inertial bisection),
154  // HSFC (for Hilbert space-filling curve partitioning),
155  // REFTREE (for refinement tree based partitioning)
156  // GRAPH (to choose from collection of methods for graphs),
157  // HYPERGRAPH (to choose from a collection of methods for hypergraphs),
158  // HIER (for hybrid hierarchical partitioning)
159  // NONE (for no load balancing).
160 
161  zoltan_handle().Set_Param( "LB_APPROACH", "PARTITION");
162  // The desired load balancing approach. Only LB_METHOD = HYPERGRAPH or GRAPH
163  // uses the LB_APPROACH parameter. Valid values are
164  // PARTITION (Partition "from scratch," not taking into account the current data distribution;
165  // this option is recommended for static load balancing.)
166  // REPARTITION (Partition but take into account current data distribution to keep data migration low;
167  // this option is recommended for dynamic load balancing.)
168  // REFINE (Quickly improve the current data distribution.)
169 
170  zoltan_handle().Set_Param( "NUM_GID_ENTRIES", "1");
171  // The number of unsigned integers that should be used to represent a global identifier (ID). Values greater than zero are accepted.
172 
173  zoltan_handle().Set_Param( "NUM_LID_ENTRIES", "0");
174  // The number of unsigned integers that should be used to represent a local identifier (ID). Values greater than or equal to zero are accepted.
175 
176  zoltan_handle().Set_Param( "RETURN_LISTS", "EXPORT");
177  // The lists returned by calls to Zoltan_LB_Partition. Valid values are
178  // "IMPORT", to return only information about objects to be imported to a processor
179  // "EXPORT", to return only information about objects to be exported from a processor
180  // "ALL", or "IMPORT AND EXPORT" (or any string with both "IMPORT" and "EXPORT" in it) to return both import and export information
181  // "PARTS" (or "PART ASSIGNMENT" or any string with "PART" in it) to return the new process and part assignment of every local object, including those not being exported.
182  // "NONE", to return neither import nor export information
183 
184 
185  zoltan_handle().Set_Param( "NUM_GLOBAL_PARTS", to_str( options()["nb_parts"].value<Uint>() ));
186  // The total number of parts to be generated by a call to Zoltan_LB_Partition.
187 
188 
190 
191  zoltan_handle().Set_Param( "GRAPH_PACKAGE", options()["graph_package"].value<std::string>() );
192  // The software package to use in partitioning the graph.
193  // PHG (default) http://www.cs.sandia.gov/zoltan/ug_html/ug_alg_phg.html
194  // ParMETIS http://www.cs.sandia.gov/zoltan/ug_html/ug_alg_parmetis.html
195  // Scotch/PT-Scotch http://www.cs.sandia.gov/zoltan/ug_html/ug_alg_ptscotch.html
196 
197  if (m_zoltan_version >= 3.5)
198  {
199  zoltan_handle().Set_Param( "GRAPH_BUILD_TYPE","FAST_NO_DUP" );
200  // Allow some optimizations in the graph building process:
201  // NORMAL = graph is generic, no optimization can be performed
202  // FAST = graph global IDs are in the interval [0,n-1], with IDs [0,a] on process 0, IDs [a+1, b] on process 1, IDs [b+1, c] on process 2, etc.
203  // FAST_NO_DUP = graph global IDs are in the interval [0,n-1], with IDs [0,a] on process 0, IDs [a+1, b] on process 1, IDs [b+1, c] on process 2, etc., and there are no duplicate edges and no need of symmetrization.
204  // See GRAPH_FAST_BUILD_BASE below to allow IDs to that are one-based instead of zero-based.
205  // Default : NORMAL
206 
207  zoltan_handle().Set_Param( "GRAPH_FAST_BUILD_BASE","0" );
208  // GRAPH_FAST_BUILD_BASE When using GRAPH_BUILD_TYPE is FAST or FAST_NO_DUP,
209  // IDs specified are in the range [GRAPH_FAST_BUILD_BASE, n-1+GRAPH_FAST_BUILD_BASE].
210  // This parameter has no effect when GRAPH_BUILD_TYPE is NORMAL.
211  // Default : GRAPH_FAST_BUILD_BASE = 0
212  }
213 
214 
215  zoltan_handle().Set_Param( "CHECK_GRAPH", to_str(std::max(2u, options()["debug_level"].value<Uint>() )));
216  // Level of error checking for graph input:
217  // 0 = no checking,
218  // 1 = on-processor checking,
219  // 2 = full checking. (CHECK_GRAPH==2 is very slow and should be used only during debugging).
220 
221  zoltan_handle().Set_Param("EDGE_WEIGHT_DIM", "1");
222 
224 
225  zoltan_handle().Set_Num_Obj_Fn(&Partitioner::query_nb_of_objects, this);
226  zoltan_handle().Set_Obj_List_Fn(&Partitioner::query_list_of_objects, this);
227  zoltan_handle().Set_Num_Edges_Multi_Fn(&Partitioner::query_nb_connected_objects, this);
228  zoltan_handle().Set_Edge_List_Multi_Fn(&Partitioner::query_list_of_connected_objects, this);
229 }
230 
232 
233 int Partitioner::query_nb_of_objects(void *data, int *ierr)
234 {
235  MeshPartitioner& p = *(MeshPartitioner *)data;
236  *ierr = ZOLTAN_OK;
237 
238  return p.nb_objects_owned_by_part(PE::Comm::instance().rank());
239 }
240 
242 
243 void Partitioner::query_list_of_objects(void *data, int sizeGID, int sizeLID,
244  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
245  int wgt_dim, float *obj_wgts, int *ierr)
246 {
247  MeshPartitioner& p = *(MeshPartitioner *)data;
248  *ierr = ZOLTAN_OK;
249 
250  p.list_of_objects_owned_by_part(PE::Comm::instance().rank(),globalID);
251 
252 
253  // for debugging
254 #if 0
255  std::vector<Uint> glbID(p.nb_objects_owned_by_part(PE::Comm::instance().rank()));
256  p.list_of_objects_owned_by_part(PE::Comm::instance().rank(),glbID);
257 
258  CFdebug << RANK << "glbID =";
259  boost_foreach(const Uint g, glbID)
260  CFdebug << " " << g;
261  CFdebug << CFendl;
262 #endif
263 
264 }
265 
267 
268 void Partitioner::query_nb_connected_objects(void *data, int sizeGID, int sizeLID, int num_obj,
269  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
270  int *numEdges, int *ierr)
271 {
272  MeshPartitioner& p = *(MeshPartitioner *)data;
273  *ierr = ZOLTAN_OK;
274 
275  p.nb_connected_objects_in_part(PE::Comm::instance().rank(),numEdges);
276 }
277 
279 
280 void Partitioner::query_list_of_connected_objects(void *data, int sizeGID, int sizeLID, int num_obj,
281  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
282  int *num_edges,
283  ZOLTAN_ID_PTR nborGID, int *nborProc,
284  int wgt_dim, float *ewgts, int *ierr)
285 {
286  MeshPartitioner& p = *(MeshPartitioner *)data;
287  *ierr = ZOLTAN_OK;
288 
289  p.list_of_connected_objects_in_part(PE::Comm::instance().rank(),nborGID, ewgts);
290  p.list_of_connected_procs_in_part(PE::Comm::instance().rank(),nborProc);
291 
292 
293 
294  // for debugging
295 #if 0
296  const Uint nb_obj = p.nb_owned_objects();
297  std::vector<Uint> numEdges(nb_obj);
298  Uint tot_nb_edges = p.nb_connected_objects(numEdges);
299 
300  std::vector<Uint> conn_glbID(tot_nb_edges);
301  p.list_of_connected_objects(conn_glbID);
302 
303  std::vector<Uint> glbID(nb_obj);
304  p.list_of_owned_objects(glbID);
305 
307  CFdebug << RANK << "conn_glbID =\n";
308  Uint cnt = 0;
309  index_foreach( e, const Uint nbEdge, numEdges)
310  {
311  if (p.is_node(glbID[e]))
312  CFdebug << " N" << p.to_node_glb(glbID[e]) << ": ";
313  else
314  CFdebug << " E" << p.to_elem_glb(glbID[e]) << ": ";
315 
316  for (Uint c=cnt; c<cnt+nbEdge; ++c)
317  {
318  if (p.is_node(conn_glbID[c]))
319  CFdebug << " N" << p.to_node_glb(conn_glbID[c]);
320  else
321  CFdebug << " E" << p.to_elem_glb(conn_glbID[c]);
322  }
323  CFdebug << "\n";
324  cnt += nbEdge;
325  }
326  CFdebug << CFendl;
327  cf3_assert( cnt == tot_nb_edges );
328  CFdebug << RANK << "total nb_edges = " << cnt << CFendl;
329  )
330 #endif
331 
332 }
333 
335 
336 #undef RANK
337 
338 } // zoltan
339 } // mesh
340 } // cf3
std::string name(ComponentWrapper &self)
void list_of_connected_procs_in_part(const Uint part, VectorT &proc_per_neighbor) const
void list_of_objects_owned_by_part(const Uint part, VectorT &obj_list) const
bool is_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:151
Helper class to create the Builder and place it in the factory.
Definition: Builder.hpp:212
Partitioner(const std::string &name)
type of pointer to Component
Definition: Partitioner.cpp:37
cf3::common::ComponentBuilder< Partitioner, MeshTransformer, LibZoltan > zoltan_partitioner_transformer_builder
Definition: Partitioner.cpp:33
#define cf3_assert(a)
Definition: Assertions.hpp:93
PropertyList & add(const std::string &name, const boost::any &value)
adds a property to the list
#define boost_foreach
lowercase version of BOOST_FOREACH
Definition: Foreach.hpp:16
void list_of_connected_objects_in_part(const Uint part, VectorT &connections_per_obj, WeightsT &edge_weights) const
boost::tuple< Uint, Uint > location_idx(const Uint glb_obj) const
#define CFendl
Definition: Log.hpp:109
Uint nb_objects_owned_by_part(const Uint part) const
Graph building functions.
Conversions from and to std::string.
Real max(const Real a, const Real b)
Maximum between two scalars.
Definition: Terminals.hpp:228
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
Common_API std::string to_str(const T &v)
Converts to std::string.
virtual ~Partitioner()
Virtual destructor.
Definition: Partitioner.cpp:61
#define RANK
Definition: Partitioner.cpp:29
#define cf3_assert_desc(m, a)
Definition: Assertions.hpp:94
bool is_node(const Uint glb_obj) const
PropertyList & properties()
Definition: Component.cpp:842
Top-level namespace for coolfluid.
Definition: Action.cpp:18
static void query_list_of_objects(void *data, int sizeGID, int sizeLID, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int wgt_dim, float *obj_wgts, int *ierr)
std::vector< std::vector< Uint > > m_nodes_to_export
nodes_to_export[part][loc_node_idx]
boost::shared_ptr< Zoltan > m_zz
Definition: Partitioner.hpp:97
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
static Core & instance()
Definition: Core.cpp:37
static int query_nb_of_objects(void *data, int *ierr)
OptionList & options()
Definition: Component.cpp:856
std::vector< std::vector< std::vector< Uint > > > m_elements_to_export
elements_to_export[part][elements_comp_idx][loc_elem_idx]
SelectOptionType< T >::type & add(const std::string &name, const T &default_value=T())
Definition: OptionList.hpp:45
#define CFdebug
Definition: Log.hpp:107
static Comm & instance()
Return a reference to the current PE.
Definition: Comm.cpp:44
Uint nb_connected_objects_in_part(const Uint part, VectorT &nb_connections_per_obj) const
static void query_nb_connected_objects(void *data, int sizeGID, int sizeLID, int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int *numEdges, int *ierr)
#define PEProcessSortedExecute(irank, expression)
Definition: debug.hpp:43
static void query_list_of_connected_objects(void *data, int sizeGID, int sizeLID, int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int *num_edges, ZOLTAN_ID_PTR nborGID, int *nborProc, int wgt_dim, float *ewgts, int *ierr)
#define FromHere()
Send comments to:
COOLFluiD Web Admin