Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
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 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)

Detailed Description

Definition at line 35 of file MetisPartitioner.hpp.


Constructor & Destructor Documentation

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

Definition at line 39 of file MetisPartitioner.cpp.

    : PartitionerBase< idx_t >( impl, use_coords )

{
}

Definition at line 45 of file MetisPartitioner.cpp.

{}

Member Function Documentation

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;
}

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 "<<part_ents.size()<<std::endl;
            result = mbImpl->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;
}

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines