Loading [MathJax]/extensions/MathMenu.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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: