Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
MetisPartitioner Class Reference

#include <MetisPartitioner.hpp>

+ Inheritance diagram for MetisPartitioner:
+ Collaboration diagram for MetisPartitioner:

Public Member Functions

 MetisPartitioner (Interface *impl=NULL, const bool use_coords=false)
 
virtual ~MetisPartitioner ()
 
virtual ErrorCode partition_mesh_and_geometry (const double part_geom_mesh_size, const idx_t nparts, const char *zmethod, const char *other_method, double imbal_tol, const int part_dim=3, const bool write_as_sets=true, const bool write_as_tags=false, const int obj_weight=0, const int edge_weight=0, const int projection_type=0, const bool recompute_rcb_box=false, const bool print_time=false)
 
virtual ErrorCode partition_mesh (const idx_t nparts, const char *method, const int part_dim=3, const bool write_as_sets=true, const bool write_as_tags=false, const bool partition_tagged_sets=false, const bool partition_tagged_ents=false, const char *aggregating_tag=NULL, const bool print_time=false)
 
virtual ErrorCode write_partition (const idx_t nparts, Range &elems, const idx_t *assignment, const bool write_as_sets, const bool write_as_tags)
 
ErrorCode write_aggregationtag_partition (const idx_t nparts, Range &elems, const idx_t *assignment, const bool write_as_sets, const bool write_as_tags)
 
virtual ErrorCode include_closure ()
 
- Public Member Functions inherited from PartitionerBase< idx_t >
 PartitionerBase (Interface *impl=NULL, const bool use_coords=false)
 
virtual ~PartitionerBase ()
 
virtual ErrorCode write_partition (const idx_t nparts, Range &elems, const idx_t *assignment, const bool write_as_sets, const bool write_as_tags)=0
 
Rangepart_sets ()
 
const Rangepart_sets () const
 
void set_global_id_option (bool id_opt)
 
bool get_global_id_option ()
 

Private Member Functions

ErrorCode assemble_graph (const int dimension, std::vector< double > &coords, std::vector< idx_t > &moab_ids, std::vector< idx_t > &adjacencies, std::vector< idx_t > &length, Range &elems)
 
ErrorCode assemble_taggedsets_graph (const int dimension, std::vector< double > &coords, std::vector< idx_t > &moab_ids, std::vector< idx_t > &adjacencies, std::vector< idx_t > &length, Range &elems, const char *aggregating_tag)
 
ErrorCode assemble_taggedents_graph (const int dimension, std::vector< double > &coords, std::vector< idx_t > &moab_ids, std::vector< idx_t > &adjacencies, std::vector< idx_t > &length, Range &elems, const char *aggregating_tag)
 

Additional Inherited Members

- Protected Attributes inherited from PartitionerBase< idx_t >
InterfacembImpl
 
bool useCoords
 
bool newComm
 
bool assign_global_ids
 
Range partSets
 

Detailed Description

Definition at line 35 of file MetisPartitioner.hpp.

Constructor & Destructor Documentation

◆ MetisPartitioner()

MetisPartitioner::MetisPartitioner ( Interface impl = NULL,
const bool  use_coords = false 
)

Definition at line 39 of file MetisPartitioner.cpp.

40  : PartitionerBase< idx_t >( impl, use_coords )
41 
42 {
43 }

◆ ~MetisPartitioner()

MetisPartitioner::~MetisPartitioner ( )
virtual

Definition at line 45 of file MetisPartitioner.cpp.

45 {}

Member Function Documentation

◆ assemble_graph()

ErrorCode MetisPartitioner::assemble_graph ( const int  dimension,
std::vector< double > &  coords,
std::vector< idx_t > &  moab_ids,
std::vector< idx_t > &  adjacencies,
std::vector< idx_t > &  length,
Range elems 
)
private

Definition at line 373 of file MetisPartitioner.cpp.

379 {
380  length.push_back( 0 );
381  // assemble a graph with vertices equal to elements of specified dimension, edges
382  // signified by list of other elements to which an element is connected
383 
384  // get the elements of that dimension
385  ErrorCode result = mbImpl->get_entities_by_dimension( 0, dimension, elems );
386  if( MB_SUCCESS != result || elems.empty() ) return result;
387 
388 #ifdef MOAB_HAVE_MPI
389  // assign global ids
390  if( assign_global_ids )
391  {
392  result = mbpc->assign_global_ids( 0, dimension, 0 );MB_CHK_ERR( result );
393  }
394 #endif
395 
396  // now assemble the graph, calling MeshTopoUtil to get bridge adjacencies through d-1
397  // dimensional neighbors
398  MeshTopoUtil mtu( mbImpl );
399  Range adjs;
400  // can use a fixed-size array 'cuz the number of lower-dimensional neighbors is limited
401  // by MBCN
402  int neighbors[5 * MAX_SUB_ENTITIES]; // these will be now indices in the elems range
403 
404  double avg_position[3];
405  int index_in_elems = 0;
406 
407  for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++, index_in_elems++ )
408  {
409 
410  // get bridge adjacencies
411  adjs.clear();
412  result = mtu.get_bridge_adjacencies( *rit, ( dimension > 0 ? dimension - 1 : 3 ), dimension, adjs );MB_CHK_ERR( result );
413 
414  // get the indices in elems range of those
415  if( !adjs.empty() )
416  {
417  int i = 0;
418  assert( adjs.size() < 5 * MAX_SUB_ENTITIES );
419  for( Range::iterator ait = adjs.begin(); ait != adjs.end(); ait++, i++ )
420  {
421  EntityHandle adjEnt = *ait;
422  neighbors[i] = elems.index( adjEnt );
423  }
424  }
425 
426  // copy those idx_to adjacencies vector
427  length.push_back( length.back() + (idx_t)adjs.size() );
428  // conversion made to idx_t
429  std::copy( neighbors, neighbors + adjs.size(), std::back_inserter( adjacencies ) );
430 
431  // get average position of vertices
432  result = mtu.get_average_position( *rit, avg_position );MB_CHK_ERR( result );
433 
434  // get the graph vertex id for this element; it is now index in elems
435  moab_ids.push_back( index_in_elems ); // conversion made to idx_t
436 
437  // copy_to coords vector
438  std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
439  }
440 
441  if( debug )
442  {
443  std::cout << "Length vector: " << std::endl;
444  std::copy( length.begin(), length.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
445  std::cout << std::endl;
446  std::cout << "Adjacencies vector: " << std::endl;
447  std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
448  std::cout << std::endl;
449  std::cout << "Moab_ids vector: " << std::endl;
450  std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
451  std::cout << std::endl;
452  std::cout << "Coords vector: " << std::endl;
453  std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( std::cout, ", " ) );
454  std::cout << std::endl;
455  }
456 
457  return MB_SUCCESS;
458 }

References PartitionerBase< idx_t >::assign_global_ids, moab::Range::begin(), moab::Range::clear(), debug, moab::Range::empty(), moab::Range::end(), ErrorCode, moab::MeshTopoUtil::get_average_position(), moab::MeshTopoUtil::get_bridge_adjacencies(), moab::Interface::get_entities_by_dimension(), moab::Range::index(), length(), moab::MAX_SUB_ENTITIES, MB_CHK_ERR, MB_SUCCESS, PartitionerBase< idx_t >::mbImpl, and moab::Range::size().

Referenced by partition_mesh().

◆ assemble_taggedents_graph()

ErrorCode MetisPartitioner::assemble_taggedents_graph ( const int  dimension,
std::vector< double > &  coords,
std::vector< idx_t > &  moab_ids,
std::vector< idx_t > &  adjacencies,
std::vector< idx_t > &  length,
Range elems,
const char *  aggregating_tag 
)
private

Definition at line 183 of file MetisPartitioner.cpp.

190 {
191  Tag partSetTag;
192  ErrorCode result = mbImpl->tag_get_handle( aggregating_tag, 1, MB_TYPE_INTEGER, partSetTag );
193  if( MB_SUCCESS != result ) return result;
194 
195  Range allSubElems;
196  result = mbImpl->get_entities_by_dimension( 0, dimension, allSubElems );
197  if( MB_SUCCESS != result || allSubElems.empty() ) return result;
198  idx_t partSet;
199  std::map< idx_t, Range > aggloElems;
200  for( Range::iterator rit = allSubElems.begin(); rit != allSubElems.end(); rit++ )
201  {
202  EntityHandle entity = *rit;
203  result = mbImpl->tag_get_data( partSetTag, &entity, 1, &partSet );
204  if( MB_SUCCESS != result ) return result;
205  if( partSet >= 0 ) aggloElems[partSet].insert( entity );
206  }
207  // clear aggregating tag data
208  TagType type;
209  result = mbImpl->tag_get_type( partSetTag, type );
210  if( type == MB_TAG_DENSE )
211  {
212  // clear tag on ents and sets
213  result = mbImpl->tag_delete( partSetTag );
214  if( MB_SUCCESS != result ) return result;
215  }
216  if( type == MB_TAG_SPARSE )
217  {
218  // clear tag on ents
219  result = mbImpl->tag_delete_data( partSetTag, allSubElems );
220  if( MB_SUCCESS != result ) return result;
221  // clear tag on sets
222  result = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &partSetTag, 0, 1, elems );
223  if( MB_SUCCESS != result ) return result;
224  result = mbImpl->tag_delete_data( partSetTag, elems );
225  if( MB_SUCCESS != result ) return result;
226  elems.clear();
227  }
228  result =
229  mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, partSetTag, MB_TAG_SPARSE | MB_TAG_CREAT );
230  if( MB_SUCCESS != result ) return result;
231 
232  for( std::map< idx_t, Range >::iterator mit = aggloElems.begin(); mit != aggloElems.end(); mit++ )
233  {
234  EntityHandle new_set;
235  result = mbImpl->create_meshset( MESHSET_SET, new_set );
236  if( MB_SUCCESS != result ) return result;
237  result = mbImpl->add_entities( new_set, mit->second );
238  if( MB_SUCCESS != result ) return result;
239  result = mbImpl->tag_set_data( partSetTag, &new_set, 1, &mit->first );
240  if( MB_SUCCESS != result ) return result;
241  }
242 
243  result =
244  assemble_taggedsets_graph( dimension, coords, moab_ids, adjacencies, length, elems, &( *aggregating_tag ) );
245  return MB_SUCCESS;
246 }

References moab::Interface::add_entities(), assemble_taggedsets_graph(), moab::Range::begin(), moab::Range::clear(), moab::Interface::create_meshset(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_dimension(), moab::Interface::get_entities_by_type_and_tag(), length(), MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< idx_t >::mbImpl, MESHSET_SET, moab::Interface::tag_delete(), moab::Interface::tag_delete_data(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_get_type(), moab::Interface::tag_set_data(), and TagType.

Referenced by partition_mesh().

◆ assemble_taggedsets_graph()

ErrorCode MetisPartitioner::assemble_taggedsets_graph ( const int  dimension,
std::vector< double > &  coords,
std::vector< idx_t > &  moab_ids,
std::vector< idx_t > &  adjacencies,
std::vector< idx_t > &  length,
Range elems,
const char *  aggregating_tag 
)
private

Definition at line 248 of file MetisPartitioner.cpp.

255 {
256  length.push_back( 0 );
257  // assemble a graph with vertices equal to elements of specified dimension, edges
258  // signified by list of other elements to which an element is connected
259 
260  // get the tagged elements
261  Tag partSetTag;
262  ErrorCode result = mbImpl->tag_get_handle( aggregating_tag, 1, MB_TYPE_INTEGER, partSetTag );MB_CHK_ERR( result );
263  // ErrorCode result = mbImpl->tag_get_handle("PARALLEL_PARTITION_SET", 1, MB_TYPE_INTEGER,
264  // partSetTag);MB_CHK_ERR(result);
265 
266  result = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &partSetTag, 0, 1, elems );
267  if( MB_SUCCESS != result || elems.empty() ) return result;
268 
269  // assign globla ids to elem sets based on aggregating_tag data
270  Tag gid_tag;
271  idx_t zero1 = -1;
272  result =
273  mbImpl->tag_get_handle( "GLOBAL_ID_AGGLO", 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_SPARSE | MB_TAG_CREAT, &zero1 );MB_CHK_ERR( result );
274  for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
275  {
276  idx_t partSet;
277  result = mbImpl->tag_get_data( partSetTag, &( *rit ), 1, &partSet );MB_CHK_ERR( result );
278  result = mbImpl->tag_set_data( gid_tag, &( *rit ), 1, &partSet );MB_CHK_ERR( result );
279  }
280  // clear aggregating tag data
281  TagType type;
282  result = mbImpl->tag_get_type( partSetTag, type );MB_CHK_ERR( result );
283  if( type == MB_TAG_DENSE )
284  {
285  result = mbImpl->tag_delete( partSetTag );MB_CHK_ERR( result );
286  }
287  if( type == MB_TAG_SPARSE )
288  {
289  result = mbImpl->tag_delete_data( partSetTag, elems );MB_CHK_ERR( result );
290  }
291 
292  // assemble the graph, using Skinner to get d-1 dimensional neighbors and then idx_tersecting to
293  // get adjacencies
294  std::vector< Range > skin_subFaces( elems.size() );
295  unsigned int i = 0;
296  for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
297  {
298  Range part_ents;
299  result = mbImpl->get_entities_by_handle( *rit, part_ents, false );
300  if( mbImpl->dimension_from_handle( *part_ents.rbegin() ) !=
301  mbImpl->dimension_from_handle( *part_ents.begin() ) )
302  {
303  Range::iterator lower = part_ents.lower_bound( CN::TypeDimensionMap[0].first ),
304  upper = part_ents.upper_bound( CN::TypeDimensionMap[dimension - 1].second );
305  part_ents.erase( lower, upper );
306  }
307  Skinner skinner( mbImpl );
308  result = skinner.find_skin( 0, part_ents, false, skin_subFaces[i], NULL, false, true, false );MB_CHK_ERR( result );
309  i++;
310  }
311  std::vector< EntityHandle > adjs;
312  std::vector< idx_t > neighbors;
313  double avg_position[3];
314  idx_t moab_id;
315  MeshTopoUtil mtu( mbImpl );
316  for( unsigned int k = 0; k < i; k++ )
317  {
318  // get bridge adjacencies for element k
319  adjs.clear();
320  for( unsigned int t = 0; t < i; t++ )
321  {
322  if( t != k )
323  {
324  Range subFaces = intersect( skin_subFaces[k], skin_subFaces[t] );
325  if( subFaces.size() > 0 ) adjs.push_back( elems[t] );
326  }
327  }
328  if( !adjs.empty() )
329  {
330  neighbors.resize( adjs.size() );
331  result = mbImpl->tag_get_data( gid_tag, &adjs[0], adjs.size(), &neighbors[0] );MB_CHK_ERR( result );
332  }
333  // copy those idx_to adjacencies vector
334  length.push_back( length.back() + (idx_t)adjs.size() );
335  std::copy( neighbors.begin(), neighbors.end(), std::back_inserter( adjacencies ) );
336  // get the graph vertex id for this element
337  const EntityHandle& setk = elems[k];
338  result = mbImpl->tag_get_data( gid_tag, &setk, 1, &moab_id );
339  moab_ids.push_back( moab_id );
340  // get average position of vertices
341  Range part_ents;
342  result = mbImpl->get_entities_by_handle( elems[k], part_ents, false );MB_CHK_ERR( result );
343  result = mtu.get_average_position( part_ents, avg_position );MB_CHK_ERR( result );
344  std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
345  }
346  for( unsigned int k = 0; k < i; k++ )
347  {
348  for( unsigned int t = 0; t < k; t++ )
349  {
350  Range subFaces = intersect( skin_subFaces[k], skin_subFaces[t] );
351  if( subFaces.size() > 0 ) mbImpl->delete_entities( subFaces );
352  }
353  }
354 
355  if( debug )
356  {
357  std::cout << "Length vector: " << std::endl;
358  std::copy( length.begin(), length.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
359  std::cout << std::endl;
360  std::cout << "Adjacencies vector: " << std::endl;
361  std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
362  std::cout << std::endl;
363  std::cout << "Moab_ids vector: " << std::endl;
364  std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
365  std::cout << std::endl;
366  std::cout << "Coords vector: " << std::endl;
367  std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( std::cout, ", " ) );
368  std::cout << std::endl;
369  }
370  return MB_SUCCESS;
371 }

References moab::Range::begin(), debug, moab::Interface::delete_entities(), moab::Interface::dimension_from_handle(), moab::Range::empty(), moab::Range::end(), moab::Range::erase(), ErrorCode, moab::Skinner::find_skin(), moab::GeomUtil::first(), moab::MeshTopoUtil::get_average_position(), moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type_and_tag(), moab::intersect(), length(), moab::Range::lower_bound(), MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< idx_t >::mbImpl, moab::Range::rbegin(), moab::Range::size(), moab::Interface::tag_delete(), moab::Interface::tag_delete_data(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_get_type(), moab::Interface::tag_set_data(), TagType, and moab::Range::upper_bound().

Referenced by assemble_taggedents_graph(), and partition_mesh().

◆ include_closure()

ErrorCode MetisPartitioner::include_closure ( )
inlinevirtual

Implements PartitionerBase< idx_t >.

Definition at line 129 of file MetisPartitioner.hpp.

130 {
131  return MB_NOT_IMPLEMENTED;
132 }

References MB_NOT_IMPLEMENTED.

◆ partition_mesh()

ErrorCode MetisPartitioner::partition_mesh ( const idx_t  nparts,
const char *  method,
const int  part_dim = 3,
const bool  write_as_sets = true,
const bool  write_as_tags = false,
const bool  partition_tagged_sets = false,
const bool  partition_tagged_ents = false,
const char *  aggregating_tag = NULL,
const bool  print_time = false 
)
virtual

Implements PartitionerBase< idx_t >.

Definition at line 47 of file MetisPartitioner.cpp.

56 {
57 #ifdef MOAB_HAVE_MPI
58  // should only be called in serial
59  if( mbpc->proc_config().proc_size() != 1 )
60  {
61  std::cout << "MetisPartitioner::partition_mesh_and_geometry must be called in serial." << std::endl;
62  return MB_FAILURE;
63  }
64 #endif
65 
66  if( NULL != method && strcmp( method, "ML_RB" ) != 0 && strcmp( method, "ML_KWAY" ) != 0 )
67  {
68  std::cout << "ERROR: Method must be "
69  << "ML_RB or ML_KWAY" << std::endl;
70  return MB_FAILURE;
71  }
72 
73  std::vector< double > pts; // x[0], y[0], z[0], ... from MOAB
74  std::vector< idx_t > ids; // poidx_t ids from MOAB
75  std::vector< idx_t > adjs, parts;
76  std::vector< idx_t > length;
77  Range elems;
78  // Get a mesh from MOAB and diide it across processors.
79 
80  clock_t t = clock();
81 
82  ErrorCode result;
83  if( !partition_tagged_sets && !partition_tagged_ents )
84  {
85  result = assemble_graph( part_dim, pts, ids, adjs, length, elems );MB_CHK_ERR( result );
86  }
87  else if( partition_tagged_sets )
88  {
89  result = assemble_taggedsets_graph( part_dim, pts, ids, adjs, length, elems, &( *aggregating_tag ) );MB_CHK_ERR( result );
90  }
91  else if( partition_tagged_ents )
92  {
93  result = assemble_taggedents_graph( part_dim, pts, ids, adjs, length, elems, &( *aggregating_tag ) );MB_CHK_ERR( result );
94  }
95  else
96  {
97  MB_SET_ERR( MB_FAILURE, "Either partition tags or sets for Metis partitoner" );
98  }
99 
100  if( print_time )
101  {
102  std::cout << " time to assemble graph: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
103  t = clock();
104  }
105 
106  std::cout << "Computing partition using " << method << " method for " << nparts << " processors..." << std::endl;
107 
108  idx_t nelems = length.size() - 1;
109  idx_t* assign_parts;
110  assign_parts = (idx_t*)malloc( sizeof( idx_t ) * nelems );
111  idx_t nconstraidx_ts = 1;
112  idx_t edgeCut = 0;
113  idx_t nOfPartitions = static_cast< idx_t >( nparts );
114  idx_t metis_RESULT;
115 
116  if( strcmp( method, "ML_KWAY" ) == 0 )
117  {
118  idx_t options[METIS_NOPTIONS];
119  METIS_SetDefaultOptions( options );
120  options[METIS_OPTION_CONTIG] = 1;
121  metis_RESULT = METIS_PartGraphKway( &nelems, &nconstraidx_ts, &length[0], &adjs[0], NULL, NULL, NULL,
122  &nOfPartitions, NULL, NULL, options, &edgeCut, assign_parts );
123  }
124  else if( strcmp( method, "ML_RB" ) == 0 )
125  {
126  idx_t options[METIS_NOPTIONS];
127  METIS_SetDefaultOptions( options );
128  options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; // CUT
129  options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_GROW; // GROW or RANDOM
130  options[METIS_OPTION_CTYPE] = METIS_CTYPE_RM; // RM or SHEM
131  options[METIS_OPTION_RTYPE] = METIS_RTYPE_FM; // FM
132  options[METIS_OPTION_NCUTS] = 10; // Number of different partitionings to compute, then
133  // chooses the best one, default = 1
134  options[METIS_OPTION_NITER] = 10; // Number of refinements steps, default = 10
135  options[METIS_OPTION_UFACTOR] = 30; // Imabalance, default = 1
136  options[METIS_OPTION_DBGLVL] = METIS_DBG_INFO;
137  metis_RESULT = METIS_PartGraphRecursive( &nelems, &nconstraidx_ts, &length[0], &adjs[0], NULL, NULL, NULL,
138  &nOfPartitions, NULL, NULL, options, &edgeCut, assign_parts );
139  }
140  else
141  MB_SET_ERR( MB_FAILURE, "Either ML_KWAY or ML_RB needs to be specified for Metis partitioner" );
142 
143  if( print_time )
144  {
145  std::cout << " time to partition: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
146  t = clock();
147  }
148 
149 #ifdef MOAB_HAVE_MPI
150  // assign global node ids, starting from one! TODO
151  if( assign_global_ids )
152  {
153  EntityHandle rootset = 0;
154  result = mbpc->assign_global_ids( rootset, part_dim, 1, true, false );MB_CHK_ERR( result );
155  }
156 #endif
157 
158  if( metis_RESULT != METIS_OK ) return MB_FAILURE;
159 
160  // take results & write onto MOAB partition sets
161  std::cout << "Saving partition information to MOAB..." << std::endl;
162  {
163  if( partition_tagged_sets || partition_tagged_ents )
164  {
165  result = write_aggregationtag_partition( nparts, elems, assign_parts, write_as_sets, write_as_tags );MB_CHK_ERR( result );
166  }
167  else
168  {
169  result = write_partition( nparts, elems, assign_parts, write_as_sets, write_as_tags );MB_CHK_ERR( result );
170  }
171  }
172 
173  if( print_time )
174  {
175  std::cout << " time to write partition in memory " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
176  t = clock();
177  }
178  free( assign_parts );
179 
180  return MB_SUCCESS;
181 }

References assemble_graph(), assemble_taggedents_graph(), assemble_taggedsets_graph(), PartitionerBase< idx_t >::assign_global_ids, ErrorCode, length(), MB_CHK_ERR, MB_SET_ERR, MB_SUCCESS, nparts, print_time(), write_aggregationtag_partition(), and write_partition().

Referenced by main().

◆ partition_mesh_and_geometry()

ErrorCode MetisPartitioner::partition_mesh_and_geometry ( const double  part_geom_mesh_size,
const idx_t  nparts,
const char *  zmethod,
const char *  other_method,
double  imbal_tol,
const int  part_dim = 3,
const bool  write_as_sets = true,
const bool  write_as_tags = false,
const int  obj_weight = 0,
const int  edge_weight = 0,
const int  projection_type = 0,
const bool  recompute_rcb_box = false,
const bool  print_time = false 
)
inlinevirtual

Implements PartitionerBase< idx_t >.

Definition at line 111 of file MetisPartitioner.hpp.

124 {
125  // Only partition the mesh - no geometric partition available
126  return partition_mesh( nparts, zmethod, part_dim, write_as_sets, write_as_tags, false, false, NULL, print_time );
127 }

References nparts, and print_time().

◆ write_aggregationtag_partition()

ErrorCode MetisPartitioner::write_aggregationtag_partition ( const idx_t  nparts,
Range elems,
const idx_t *  assignment,
const bool  write_as_sets,
const bool  write_as_tags 
)

Definition at line 460 of file MetisPartitioner.cpp.

465 {
466  ErrorCode result;
467 
468  // get the partition set tag
469  Tag part_set_tag;
470  result =
471  mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, part_set_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( result );
472 
473  // get any sets already with this tag, and clear them
474  Range tagged_sets;
475  result =
476  mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &part_set_tag, NULL, 1, tagged_sets, Interface::UNION );MB_CHK_ERR( result );
477  if( !tagged_sets.empty() )
478  {
479  result = mbImpl->clear_meshset( tagged_sets );
480  if( !write_as_sets )
481  {
482  result = mbImpl->tag_delete_data( part_set_tag, tagged_sets );MB_CHK_ERR( result );
483  }
484  }
485 
486  if( write_as_sets )
487  {
488  // first, create partition sets and store in vector
489  partSets.clear();
490 
491  if( nparts > (idx_t)tagged_sets.size() )
492  {
493  // too few partition sets - create missing ones
494  idx_t num_new = nparts - tagged_sets.size();
495  for( idx_t i = 0; i < num_new; i++ )
496  {
497  EntityHandle new_set;
498  result = mbImpl->create_meshset( MESHSET_SET, new_set );MB_CHK_ERR( result );
499  tagged_sets.insert( new_set );
500  }
501  }
502  else if( nparts < (idx_t)tagged_sets.size() )
503  {
504  // too many partition sets - delete extras
505  idx_t num_del = tagged_sets.size() - nparts;
506  for( idx_t i = 0; i < num_del; i++ )
507  {
508  EntityHandle old_set = tagged_sets.pop_back();
509  result = mbImpl->delete_entities( &old_set, 1 );MB_CHK_ERR( result );
510  }
511  }
512 
513  // assign partition sets to vector
514  partSets.swap( tagged_sets );
515 
516  // write a tag to those sets denoting they're partition sets, with a value of the
517  // proc number
518  idx_t* dum_ids = new idx_t[nparts];
519  for( idx_t i = 0; i < nparts; i++ )
520  dum_ids[i] = i;
521 
522  result = mbImpl->tag_set_data( part_set_tag, partSets, dum_ids );MB_CHK_ERR( result );
523 
524  // assign entities to the relevant sets
525  std::vector< EntityHandle > tmp_part_sets;
526  std::copy( partSets.begin(), partSets.end(), std::back_inserter( tmp_part_sets ) );
527  Range::iterator rit;
528  unsigned j = 0;
529  for( rit = elems.begin(); rit != elems.end(); rit++, j++ )
530  {
531  result = mbImpl->add_entities( tmp_part_sets[assignment[j]], &( *rit ), 1 );MB_CHK_ERR( result );
532  }
533 
534  // check for empty sets, warn if there are any
535  Range empty_sets;
536  for( rit = partSets.begin(); rit != partSets.end(); rit++ )
537  {
538  int num_ents = 0;
539  result = mbImpl->get_number_entities_by_handle( *rit, num_ents );
540  if( MB_SUCCESS != result || !num_ents ) empty_sets.insert( *rit );
541  }
542  if( !empty_sets.empty() )
543  {
544  std::cout << "WARNING: " << empty_sets.size() << " empty sets in partition: ";
545  for( rit = empty_sets.begin(); rit != empty_sets.end(); rit++ )
546  std::cout << *rit << " ";
547  std::cout << std::endl;
548  }
549  }
550 
551  if( write_as_tags )
552  {
553  Tag gid_tag;
554  result = mbImpl->tag_get_handle( "GLOBAL_ID_AGGLO", 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_SPARSE );MB_CHK_ERR( result );
555 
556  // allocate idx_teger-size partitions
557  unsigned int i = 0;
558  idx_t gid;
559  for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
560  {
561  result = mbImpl->tag_get_data( gid_tag, &( *rit ), 1, &gid );
562  Range part_ents;
563  // std::cout<<"part ents "<<part_ents.size()<<std::endl;
564  result = mbImpl->get_entities_by_handle( *rit, part_ents, false );MB_CHK_ERR( result );
565 
566  for( Range::iterator eit = part_ents.begin(); eit != part_ents.end(); eit++ )
567  {
568  result = mbImpl->tag_set_data( part_set_tag, &( *eit ), 1, &assignment[i] );MB_CHK_ERR( result );
569 
570  result = mbImpl->tag_set_data( gid_tag, &( *eit ), 1, &gid );MB_CHK_ERR( result );
571  }
572  i++;
573  }
574  }
575  return MB_SUCCESS;
576 }

References moab::Interface::add_entities(), moab::Range::begin(), moab::Range::clear(), moab::Interface::clear_meshset(), moab::Interface::create_meshset(), moab::Interface::delete_entities(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type_and_tag(), moab::Interface::get_number_entities_by_handle(), moab::Range::insert(), MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< idx_t >::mbImpl, MESHSET_SET, nparts, PartitionerBase< idx_t >::partSets, moab::Range::pop_back(), moab::Range::size(), moab::Range::swap(), moab::Interface::tag_delete_data(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), and moab::Interface::tag_set_data().

Referenced by partition_mesh().

◆ write_partition()

ErrorCode MetisPartitioner::write_partition ( const idx_t  nparts,
Range elems,
const idx_t *  assignment,
const bool  write_as_sets,
const bool  write_as_tags 
)
virtual

Definition at line 578 of file MetisPartitioner.cpp.

583 {
584  ErrorCode result;
585 
586  // get the partition set tag
587  Tag part_set_tag;
588  idx_t dum_id = -1, i;
589  result = mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, part_set_tag,
590  MB_TAG_SPARSE | MB_TAG_CREAT, &dum_id );MB_CHK_ERR( result );
591 
592  // get any sets already with this tag, and clear them
593  Range tagged_sets;
594  result =
595  mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &part_set_tag, NULL, 1, tagged_sets, Interface::UNION );MB_CHK_ERR( result );
596  if( !tagged_sets.empty() )
597  {
598  result = mbImpl->clear_meshset( tagged_sets );
599  if( !write_as_sets )
600  {
601  result = mbImpl->tag_delete_data( part_set_tag, tagged_sets );MB_CHK_ERR( result );
602  }
603  }
604 
605  if( write_as_sets )
606  {
607  // first, create partition sets and store in vector
608  partSets.clear();
609 
610  if( nparts > (int)tagged_sets.size() )
611  {
612  // too few partition sets - create missing ones
613  idx_t num_new = nparts - tagged_sets.size();
614  for( i = 0; i < num_new; i++ )
615  {
616  EntityHandle new_set;
617  result = mbImpl->create_meshset( MESHSET_SET, new_set );MB_CHK_ERR( result );
618  tagged_sets.insert( new_set );
619  }
620  }
621  else if( nparts < (idx_t)tagged_sets.size() )
622  {
623  // too many partition sets - delete extras
624  idx_t num_del = tagged_sets.size() - nparts;
625  for( i = 0; i < num_del; i++ )
626  {
627  EntityHandle old_set = tagged_sets.pop_back();
628  result = mbImpl->delete_entities( &old_set, 1 );MB_CHK_ERR( result );
629  }
630  }
631 
632  // assign partition sets to vector
633  partSets.swap( tagged_sets );
634 
635  // write a tag to those sets denoting they're partition sets, with a value of the
636  // proc number
637  int* dum_ids = new int[nparts]; // this remains integer
638  for( i = 0; i < nparts; i++ )
639  dum_ids[i] = i;
640 
641  result = mbImpl->tag_set_data( part_set_tag, partSets, dum_ids );
642  delete[] dum_ids;
643 
644  // assign entities to the relevant sets
645  std::vector< EntityHandle > tmp_part_sets;
646  std::copy( partSets.begin(), partSets.end(), std::back_inserter( tmp_part_sets ) );
647  Range::iterator rit;
648  for( i = 0, rit = elems.begin(); rit != elems.end(); rit++, i++ )
649  {
650  result = mbImpl->add_entities( tmp_part_sets[assignment[i]], &( *rit ), 1 );MB_CHK_ERR( result );
651  }
652 
653  // check for empty sets, warn if there are any
654  Range empty_sets;
655  for( rit = partSets.begin(); rit != partSets.end(); rit++ )
656  {
657  int num_ents = 0;
658  result = mbImpl->get_number_entities_by_handle( *rit, num_ents );
659  if( MB_SUCCESS != result || !num_ents ) empty_sets.insert( *rit );
660  }
661  if( !empty_sets.empty() )
662  {
663  std::cout << "WARNING: " << empty_sets.size() << " empty sets in partition: ";
664  for( rit = empty_sets.begin(); rit != empty_sets.end(); rit++ )
665  std::cout << *rit << " ";
666  std::cout << std::endl;
667  }
668  }
669 
670  if( write_as_tags )
671  {
672  if( sizeof( int ) != sizeof( idx_t ) )
673  {
674  // allocate idx_teger-size partitions
675  // first we have to copy to int, then assign
676  int* assg_int = new int[elems.size()];
677  for( int k = 0; k < (int)elems.size(); k++ )
678  assg_int[k] = assignment[k];
679  result = mbImpl->tag_set_data( part_set_tag, elems, assg_int );MB_CHK_ERR( result );
680  delete[] assg_int;
681  }
682  else
683  result = mbImpl->tag_set_data( part_set_tag, elems, assignment );MB_CHK_ERR( result );
684  }
685 
686  return MB_SUCCESS;
687 }

References moab::Interface::add_entities(), moab::Range::begin(), moab::Range::clear(), moab::Interface::clear_meshset(), moab::Interface::create_meshset(), moab::Interface::delete_entities(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_type_and_tag(), moab::Interface::get_number_entities_by_handle(), moab::Range::insert(), MB_CHK_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< idx_t >::mbImpl, MESHSET_SET, nparts, PartitionerBase< idx_t >::partSets, moab::Range::pop_back(), moab::Range::size(), moab::Range::swap(), moab::Interface::tag_delete_data(), moab::Interface::tag_get_handle(), and moab::Interface::tag_set_data().

Referenced by partition_mesh().


The documentation for this class was generated from the following files: