![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
#include <MetisPartitioner.hpp>
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 bool part_surf=false, const bool ghost=false, 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 () |
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) |
Definition at line 35 of file MetisPartitioner.hpp.
MetisPartitioner::MetisPartitioner | ( | Interface * | impl = NULL , |
const bool | use_coords = false |
||
) |
Definition at line 39 of file MetisPartitioner.cpp.
: PartitionerBase< idx_t >( impl, use_coords )
{
}
MetisPartitioner::~MetisPartitioner | ( | ) | [virtual] |
Definition at line 45 of file MetisPartitioner.cpp.
{}
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.
References PartitionerBase< idx_t >::assign_global_ids, moab::Range::begin(), moab::Range::clear(), moab::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(), moab::MAX_SUB_ENTITIES, MB_CHK_ERR, MB_SUCCESS, PartitionerBase< idx_t >::mbImpl, and moab::Range::size().
Referenced by partition_mesh().
{
length.push_back( 0 );
// assemble a graph with vertices equal to elements of specified dimension, edges
// signified by list of other elements to which an element is connected
// get the elements of that dimension
ErrorCode result = mbImpl->get_entities_by_dimension( 0, dimension, elems );
if( MB_SUCCESS != result || elems.empty() ) return result;
#ifdef MOAB_HAVE_MPI
// assign global ids
if( assign_global_ids )
{
result = mbpc->assign_global_ids( 0, dimension, 0 );MB_CHK_ERR( result );
}
#endif
// now assemble the graph, calling MeshTopoUtil to get bridge adjacencies through d-1
// dimensional neighbors
MeshTopoUtil mtu( mbImpl );
Range adjs;
// can use a fixed-size array 'cuz the number of lower-dimensional neighbors is limited
// by MBCN
int neighbors[5 * MAX_SUB_ENTITIES]; // these will be now indices in the elems range
double avg_position[3];
int index_in_elems = 0;
for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++, index_in_elems++ )
{
// get bridge adjacencies
adjs.clear();
result = mtu.get_bridge_adjacencies( *rit, ( dimension > 0 ? dimension - 1 : 3 ), dimension, adjs );MB_CHK_ERR( result );
// get the indices in elems range of those
if( !adjs.empty() )
{
int i = 0;
assert( adjs.size() < 5 * MAX_SUB_ENTITIES );
for( Range::iterator ait = adjs.begin(); ait != adjs.end(); ait++, i++ )
{
EntityHandle adjEnt = *ait;
neighbors[i] = elems.index( adjEnt );
}
}
// copy those idx_to adjacencies vector
length.push_back( length.back() + (idx_t)adjs.size() );
// conversion made to idx_t
std::copy( neighbors, neighbors + adjs.size(), std::back_inserter( adjacencies ) );
// get average position of vertices
result = mtu.get_average_position( *rit, avg_position );MB_CHK_ERR( result );
// get the graph vertex id for this element; it is now index in elems
moab_ids.push_back( index_in_elems ); // conversion made to idx_t
// copy_to coords vector
std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
}
if( debug )
{
std::cout << "Length vector: " << std::endl;
std::copy( length.begin(), length.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Adjacencies vector: " << std::endl;
std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Moab_ids vector: " << std::endl;
std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Coords vector: " << std::endl;
std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( std::cout, ", " ) );
std::cout << std::endl;
}
return MB_SUCCESS;
}
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.
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(), 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().
{
Tag partSetTag;
ErrorCode result = mbImpl->tag_get_handle( aggregating_tag, 1, MB_TYPE_INTEGER, partSetTag );
if( MB_SUCCESS != result ) return result;
Range allSubElems;
result = mbImpl->get_entities_by_dimension( 0, dimension, allSubElems );
if( MB_SUCCESS != result || allSubElems.empty() ) return result;
idx_t partSet;
std::map< idx_t, Range > aggloElems;
for( Range::iterator rit = allSubElems.begin(); rit != allSubElems.end(); rit++ )
{
EntityHandle entity = *rit;
result = mbImpl->tag_get_data( partSetTag, &entity, 1, &partSet );
if( MB_SUCCESS != result ) return result;
if( partSet >= 0 ) aggloElems[partSet].insert( entity );
}
// clear aggregating tag data
TagType type;
result = mbImpl->tag_get_type( partSetTag, type );
if( type == MB_TAG_DENSE )
{
// clear tag on ents and sets
result = mbImpl->tag_delete( partSetTag );
if( MB_SUCCESS != result ) return result;
}
if( type == MB_TAG_SPARSE )
{
// clear tag on ents
result = mbImpl->tag_delete_data( partSetTag, allSubElems );
if( MB_SUCCESS != result ) return result;
// clear tag on sets
result = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &partSetTag, 0, 1, elems );
if( MB_SUCCESS != result ) return result;
result = mbImpl->tag_delete_data( partSetTag, elems );
if( MB_SUCCESS != result ) return result;
elems.clear();
}
result =
mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, partSetTag, MB_TAG_SPARSE | MB_TAG_CREAT );
if( MB_SUCCESS != result ) return result;
for( std::map< idx_t, Range >::iterator mit = aggloElems.begin(); mit != aggloElems.end(); mit++ )
{
EntityHandle new_set;
result = mbImpl->create_meshset( MESHSET_SET, new_set );
if( MB_SUCCESS != result ) return result;
result = mbImpl->add_entities( new_set, mit->second );
if( MB_SUCCESS != result ) return result;
result = mbImpl->tag_set_data( partSetTag, &new_set, 1, &mit->first );
if( MB_SUCCESS != result ) return result;
}
result =
assemble_taggedsets_graph( dimension, coords, moab_ids, adjacencies, length, elems, &( *aggregating_tag ) );
return MB_SUCCESS;
}
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.
References moab::Range::begin(), moab::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(), 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(), t, 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().
{
length.push_back( 0 );
// assemble a graph with vertices equal to elements of specified dimension, edges
// signified by list of other elements to which an element is connected
// get the tagged elements
Tag partSetTag;
ErrorCode result = mbImpl->tag_get_handle( aggregating_tag, 1, MB_TYPE_INTEGER, partSetTag );MB_CHK_ERR( result );
// ErrorCode result = mbImpl->tag_get_handle("PARALLEL_PARTITION_SET", 1, MB_TYPE_INTEGER,
// partSetTag);MB_CHK_ERR(result);
result = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &partSetTag, 0, 1, elems );
if( MB_SUCCESS != result || elems.empty() ) return result;
// assign globla ids to elem sets based on aggregating_tag data
Tag gid_tag;
idx_t zero1 = -1;
result =
mbImpl->tag_get_handle( "GLOBAL_ID_AGGLO", 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_SPARSE | MB_TAG_CREAT, &zero1 );MB_CHK_ERR( result );
for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
{
idx_t partSet;
result = mbImpl->tag_get_data( partSetTag, &( *rit ), 1, &partSet );MB_CHK_ERR( result );
result = mbImpl->tag_set_data( gid_tag, &( *rit ), 1, &partSet );MB_CHK_ERR( result );
}
// clear aggregating tag data
TagType type;
result = mbImpl->tag_get_type( partSetTag, type );MB_CHK_ERR( result );
if( type == MB_TAG_DENSE )
{
result = mbImpl->tag_delete( partSetTag );MB_CHK_ERR( result );
}
if( type == MB_TAG_SPARSE )
{
result = mbImpl->tag_delete_data( partSetTag, elems );MB_CHK_ERR( result );
}
// assemble the graph, using Skinner to get d-1 dimensional neighbors and then idx_tersecting to
// get adjacencies
std::vector< Range > skin_subFaces( elems.size() );
unsigned int i = 0;
for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
{
Range part_ents;
result = mbImpl->get_entities_by_handle( *rit, part_ents, false );
if( mbImpl->dimension_from_handle( *part_ents.rbegin() ) !=
mbImpl->dimension_from_handle( *part_ents.begin() ) )
{
Range::iterator lower = part_ents.lower_bound( CN::TypeDimensionMap[0].first ),
upper = part_ents.upper_bound( CN::TypeDimensionMap[dimension - 1].second );
part_ents.erase( lower, upper );
}
Skinner skinner( mbImpl );
result = skinner.find_skin( 0, part_ents, false, skin_subFaces[i], NULL, false, true, false );MB_CHK_ERR( result );
i++;
}
std::vector< EntityHandle > adjs;
std::vector< idx_t > neighbors;
double avg_position[3];
idx_t moab_id;
MeshTopoUtil mtu( mbImpl );
for( unsigned int k = 0; k < i; k++ )
{
// get bridge adjacencies for element k
adjs.clear();
for( unsigned int t = 0; t < i; t++ )
{
if( t != k )
{
Range subFaces = intersect( skin_subFaces[k], skin_subFaces[t] );
if( subFaces.size() > 0 ) adjs.push_back( elems[t] );
}
}
if( !adjs.empty() )
{
neighbors.resize( adjs.size() );
result = mbImpl->tag_get_data( gid_tag, &adjs[0], adjs.size(), &neighbors[0] );MB_CHK_ERR( result );
}
// copy those idx_to adjacencies vector
length.push_back( length.back() + (idx_t)adjs.size() );
std::copy( neighbors.begin(), neighbors.end(), std::back_inserter( adjacencies ) );
// get the graph vertex id for this element
const EntityHandle& setk = elems[k];
result = mbImpl->tag_get_data( gid_tag, &setk, 1, &moab_id );
moab_ids.push_back( moab_id );
// get average position of vertices
Range part_ents;
result = mbImpl->get_entities_by_handle( elems[k], part_ents, false );MB_CHK_ERR( result );
result = mtu.get_average_position( part_ents, avg_position );MB_CHK_ERR( result );
std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
}
for( unsigned int k = 0; k < i; k++ )
{
for( unsigned int t = 0; t < k; t++ )
{
Range subFaces = intersect( skin_subFaces[k], skin_subFaces[t] );
if( subFaces.size() > 0 ) mbImpl->delete_entities( subFaces );
}
}
if( debug )
{
std::cout << "Length vector: " << std::endl;
std::copy( length.begin(), length.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Adjacencies vector: " << std::endl;
std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Moab_ids vector: " << std::endl;
std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< idx_t >( std::cout, ", " ) );
std::cout << std::endl;
std::cout << "Coords vector: " << std::endl;
std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( std::cout, ", " ) );
std::cout << std::endl;
}
return MB_SUCCESS;
}
ErrorCode MetisPartitioner::include_closure | ( | ) | [inline, virtual] |
Implements PartitionerBase< idx_t >.
Definition at line 133 of file MetisPartitioner.hpp.
References MB_NOT_IMPLEMENTED.
{
return MB_NOT_IMPLEMENTED;
}
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.
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, t, write_aggregationtag_partition(), and write_partition().
Referenced by main().
{
#ifdef MOAB_HAVE_MPI
// should only be called in serial
if( mbpc->proc_config().proc_size() != 1 )
{
std::cout << "MetisPartitioner::partition_mesh_and_geometry must be called in serial." << std::endl;
return MB_FAILURE;
}
#endif
if( NULL != method && strcmp( method, "ML_RB" ) != 0 && strcmp( method, "ML_KWAY" ) != 0 )
{
std::cout << "ERROR: Method must be "
<< "ML_RB or ML_KWAY" << std::endl;
return MB_FAILURE;
}
std::vector< double > pts; // x[0], y[0], z[0], ... from MOAB
std::vector< idx_t > ids; // poidx_t ids from MOAB
std::vector< idx_t > adjs, parts;
std::vector< idx_t > length;
Range elems;
// Get a mesh from MOAB and diide it across processors.
clock_t t = clock();
ErrorCode result;
if( !partition_tagged_sets && !partition_tagged_ents )
{
result = assemble_graph( part_dim, pts, ids, adjs, length, elems );MB_CHK_ERR( result );
}
else if( partition_tagged_sets )
{
result = assemble_taggedsets_graph( part_dim, pts, ids, adjs, length, elems, &( *aggregating_tag ) );MB_CHK_ERR( result );
}
else if( partition_tagged_ents )
{
result = assemble_taggedents_graph( part_dim, pts, ids, adjs, length, elems, &( *aggregating_tag ) );MB_CHK_ERR( result );
}
else
{
MB_SET_ERR( MB_FAILURE, "Either partition tags or sets for Metis partitoner" );
}
if( print_time )
{
std::cout << " time to assemble graph: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
t = clock();
}
std::cout << "Computing partition using " << method << " method for " << nparts << " processors..." << std::endl;
idx_t nelems = length.size() - 1;
idx_t* assign_parts;
assign_parts = (idx_t*)malloc( sizeof( idx_t ) * nelems );
idx_t nconstraidx_ts = 1;
idx_t edgeCut = 0;
idx_t nOfPartitions = static_cast< idx_t >( nparts );
idx_t metis_RESULT;
if( strcmp( method, "ML_KWAY" ) == 0 )
{
idx_t options[METIS_NOPTIONS];
METIS_SetDefaultOptions( options );
options[METIS_OPTION_CONTIG] = 1;
metis_RESULT = METIS_PartGraphKway( &nelems, &nconstraidx_ts, &length[0], &adjs[0], NULL, NULL, NULL,
&nOfPartitions, NULL, NULL, options, &edgeCut, assign_parts );
}
else if( strcmp( method, "ML_RB" ) == 0 )
{
idx_t options[METIS_NOPTIONS];
METIS_SetDefaultOptions( options );
options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; // CUT
options[METIS_OPTION_IPTYPE] = METIS_IPTYPE_GROW; // GROW or RANDOM
options[METIS_OPTION_CTYPE] = METIS_CTYPE_RM; // RM or SHEM
options[METIS_OPTION_RTYPE] = METIS_RTYPE_FM; // FM
options[METIS_OPTION_NCUTS] = 10; // Number of different partitionings to compute, then
// chooses the best one, default = 1
options[METIS_OPTION_NITER] = 10; // Number of refinements steps, default = 10
options[METIS_OPTION_UFACTOR] = 30; // Imabalance, default = 1
options[METIS_OPTION_DBGLVL] = METIS_DBG_INFO;
metis_RESULT = METIS_PartGraphRecursive( &nelems, &nconstraidx_ts, &length[0], &adjs[0], NULL, NULL, NULL,
&nOfPartitions, NULL, NULL, options, &edgeCut, assign_parts );
}
else
MB_SET_ERR( MB_FAILURE, "Either ML_KWAY or ML_RB needs to be specified for Metis partitioner" );
if( print_time )
{
std::cout << " time to partition: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
t = clock();
}
#ifdef MOAB_HAVE_MPI
// assign global node ids, starting from one! TODO
if( assign_global_ids )
{
EntityHandle rootset = 0;
result = mbpc->assign_global_ids( rootset, part_dim, 1, true, false );MB_CHK_ERR( result );
}
#endif
if( metis_RESULT != METIS_OK ) return MB_FAILURE;
// take results & write onto MOAB partition sets
std::cout << "Saving partition information to MOAB..." << std::endl;
{
if( partition_tagged_sets || partition_tagged_ents )
{
result = write_aggregationtag_partition( nparts, elems, assign_parts, write_as_sets, write_as_tags );MB_CHK_ERR( result );
}
else
{
result = write_partition( nparts, elems, assign_parts, write_as_sets, write_as_tags );MB_CHK_ERR( result );
}
}
if( print_time )
{
std::cout << " time to write partition in memory " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n";
t = clock();
}
free( assign_parts );
return MB_SUCCESS;
}
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 bool | part_surf = false , |
||
const bool | ghost = false , |
||
const int | projection_type = 0 , |
||
const bool | recompute_rcb_box = false , |
||
const bool | print_time = false |
||
) | [inline, virtual] |
Implements PartitionerBase< idx_t >.
Definition at line 113 of file MetisPartitioner.hpp.
{
// Only partition the mesh - no geometric partition available
return partition_mesh( nparts, zmethod, part_dim, write_as_sets, write_as_tags, false, false, NULL, print_time );
}
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.
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(), moab::Interface::tag_set_data(), and smoab::UNION.
Referenced by partition_mesh().
{
ErrorCode result;
// get the partition set tag
Tag part_set_tag;
result =
mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, part_set_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( result );
// get any sets already with this tag, and clear them
Range tagged_sets;
result =
mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &part_set_tag, NULL, 1, tagged_sets, Interface::UNION );MB_CHK_ERR( result );
if( !tagged_sets.empty() )
{
result = mbImpl->clear_meshset( tagged_sets );
if( !write_as_sets )
{
result = mbImpl->tag_delete_data( part_set_tag, tagged_sets );MB_CHK_ERR( result );
}
}
if( write_as_sets )
{
// first, create partition sets and store in vector
partSets.clear();
if( nparts > (idx_t)tagged_sets.size() )
{
// too few partition sets - create missing ones
idx_t num_new = nparts - tagged_sets.size();
for( idx_t i = 0; i < num_new; i++ )
{
EntityHandle new_set;
result = mbImpl->create_meshset( MESHSET_SET, new_set );MB_CHK_ERR( result );
tagged_sets.insert( new_set );
}
}
else if( nparts < (idx_t)tagged_sets.size() )
{
// too many partition sets - delete extras
idx_t num_del = tagged_sets.size() - nparts;
for( idx_t i = 0; i < num_del; i++ )
{
EntityHandle old_set = tagged_sets.pop_back();
result = mbImpl->delete_entities( &old_set, 1 );MB_CHK_ERR( result );
}
}
// assign partition sets to vector
partSets.swap( tagged_sets );
// write a tag to those sets denoting they're partition sets, with a value of the
// proc number
idx_t* dum_ids = new idx_t[nparts];
for( idx_t i = 0; i < nparts; i++ )
dum_ids[i] = i;
result = mbImpl->tag_set_data( part_set_tag, partSets, dum_ids );MB_CHK_ERR( result );
// assign entities to the relevant sets
std::vector< EntityHandle > tmp_part_sets;
std::copy( partSets.begin(), partSets.end(), std::back_inserter( tmp_part_sets ) );
Range::iterator rit;
unsigned j = 0;
for( rit = elems.begin(); rit != elems.end(); rit++, j++ )
{
result = mbImpl->add_entities( tmp_part_sets[assignment[j]], &( *rit ), 1 );MB_CHK_ERR( result );
}
// check for empty sets, warn if there are any
Range empty_sets;
for( rit = partSets.begin(); rit != partSets.end(); rit++ )
{
int num_ents = 0;
result = mbImpl->get_number_entities_by_handle( *rit, num_ents );
if( MB_SUCCESS != result || !num_ents ) empty_sets.insert( *rit );
}
if( !empty_sets.empty() )
{
std::cout << "WARNING: " << empty_sets.size() << " empty sets in partition: ";
for( rit = empty_sets.begin(); rit != empty_sets.end(); rit++ )
std::cout << *rit << " ";
std::cout << std::endl;
}
}
if( write_as_tags )
{
Tag gid_tag;
result = mbImpl->tag_get_handle( "GLOBAL_ID_AGGLO", 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_SPARSE );MB_CHK_ERR( result );
// allocate idx_teger-size partitions
unsigned int i = 0;
idx_t gid;
for( Range::iterator rit = elems.begin(); rit != elems.end(); rit++ )
{
result = mbImpl->tag_get_data( gid_tag, &( *rit ), 1, &gid );
Range part_ents;
// std::cout<<"part ents "<get_entities_by_handle( *rit, part_ents, false );MB_CHK_ERR( result );
for( Range::iterator eit = part_ents.begin(); eit != part_ents.end(); eit++ )
{
result = mbImpl->tag_set_data( part_set_tag, &( *eit ), 1, &assignment[i] );MB_CHK_ERR( result );
result = mbImpl->tag_set_data( gid_tag, &( *eit ), 1, &gid );MB_CHK_ERR( result );
}
i++;
}
}
return MB_SUCCESS;
}
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.
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(), moab::Interface::tag_set_data(), and smoab::UNION.
Referenced by partition_mesh().
{
ErrorCode result;
// get the partition set tag
Tag part_set_tag;
idx_t dum_id = -1, i;
result = mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, part_set_tag,
MB_TAG_SPARSE | MB_TAG_CREAT, &dum_id );MB_CHK_ERR( result );
// get any sets already with this tag, and clear them
Range tagged_sets;
result =
mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &part_set_tag, NULL, 1, tagged_sets, Interface::UNION );MB_CHK_ERR( result );
if( !tagged_sets.empty() )
{
result = mbImpl->clear_meshset( tagged_sets );
if( !write_as_sets )
{
result = mbImpl->tag_delete_data( part_set_tag, tagged_sets );MB_CHK_ERR( result );
}
}
if( write_as_sets )
{
// first, create partition sets and store in vector
partSets.clear();
if( nparts > (int)tagged_sets.size() )
{
// too few partition sets - create missing ones
idx_t num_new = nparts - tagged_sets.size();
for( i = 0; i < num_new; i++ )
{
EntityHandle new_set;
result = mbImpl->create_meshset( MESHSET_SET, new_set );MB_CHK_ERR( result );
tagged_sets.insert( new_set );
}
}
else if( nparts < (idx_t)tagged_sets.size() )
{
// too many partition sets - delete extras
idx_t num_del = tagged_sets.size() - nparts;
for( i = 0; i < num_del; i++ )
{
EntityHandle old_set = tagged_sets.pop_back();
result = mbImpl->delete_entities( &old_set, 1 );MB_CHK_ERR( result );
}
}
// assign partition sets to vector
partSets.swap( tagged_sets );
// write a tag to those sets denoting they're partition sets, with a value of the
// proc number
int* dum_ids = new int[nparts]; // this remains integer
for( i = 0; i < nparts; i++ )
dum_ids[i] = i;
result = mbImpl->tag_set_data( part_set_tag, partSets, dum_ids );
delete[] dum_ids;
// assign entities to the relevant sets
std::vector< EntityHandle > tmp_part_sets;
std::copy( partSets.begin(), partSets.end(), std::back_inserter( tmp_part_sets ) );
Range::iterator rit;
for( i = 0, rit = elems.begin(); rit != elems.end(); rit++, i++ )
{
result = mbImpl->add_entities( tmp_part_sets[assignment[i]], &( *rit ), 1 );MB_CHK_ERR( result );
}
// check for empty sets, warn if there are any
Range empty_sets;
for( rit = partSets.begin(); rit != partSets.end(); rit++ )
{
int num_ents = 0;
result = mbImpl->get_number_entities_by_handle( *rit, num_ents );
if( MB_SUCCESS != result || !num_ents ) empty_sets.insert( *rit );
}
if( !empty_sets.empty() )
{
std::cout << "WARNING: " << empty_sets.size() << " empty sets in partition: ";
for( rit = empty_sets.begin(); rit != empty_sets.end(); rit++ )
std::cout << *rit << " ";
std::cout << std::endl;
}
}
if( write_as_tags )
{
if( sizeof( int ) != sizeof( idx_t ) )
{
// allocate idx_teger-size partitions
// first we have to copy to int, then assign
int* assg_int = new int[elems.size()];
for( int k = 0; k < (int)elems.size(); k++ )
assg_int[k] = assignment[k];
result = mbImpl->tag_set_data( part_set_tag, elems, assg_int );MB_CHK_ERR( result );
delete[] assg_int;
}
else
result = mbImpl->tag_set_data( part_set_tag, elems, assignment );MB_CHK_ERR( result );
}
return MB_SUCCESS;
}