Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
#include <ZoltanPartitioner.hpp>
Public Member Functions | |
ZoltanPartitioner (Interface *impl=NULL, const bool use_coords=false, int argc=0, char **argv=NULL) | |
virtual | ~ZoltanPartitioner () |
ErrorCode | balance_mesh (const char *zmethod, const char *other_method, const bool write_as_sets=true, const bool write_as_tags=false) |
virtual ErrorCode | partition_mesh_and_geometry (const double part_geom_mesh_size, const int 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 int 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) |
ErrorCode | partition_inferred_mesh (EntityHandle sfileset, size_t num_parts, int part_dim=3, const bool write_as_sets=true, int projection_type=0) |
virtual ErrorCode | write_partition (const int nparts, Range &elems, const int *assignment, const bool write_as_sets, const bool write_as_tags) |
ErrorCode | repartition (std::vector< double > &x, std::vector< double > &y, std::vector< double > &z, int StartID, const char *zmethod, Range &localGIDs) |
ErrorCode | partition_owned_cells (Range &owned, std::multimap< int, int > &extraGraphEdges, std::map< int, int > procs, int &numNewPartitions, std::map< int, Range > &distribution, int met, std::vector< char > &ZoltanBuffer) |
ErrorCode | include_closure () |
void | SetOCTPART_Parameters (const char *oct_method) |
void | SetPARMETIS_Parameters (const char *parmetis_method) |
void | SetHypergraph_Parameters (const char *phg_method) |
void | SetHSFC_Parameters () |
void | SetRIB_Parameters () |
void | SetRCB_Parameters (const bool recompute_rcb_box=false) |
Private Member Functions | |
int | mbGlobalSuccess (int rc) |
void | mbPrintGlobalResult (const char *s, int begin, int import, int exp, int change) |
void | mbShowError (int val, const char *s) |
ErrorCode | assemble_graph (const int dimension, std::vector< double > &coords, std::vector< int > &moab_ids, std::vector< int > &adjacencies, std::vector< int > &length, Range &elems, bool part_geom=false, const int projection_type=0) |
void | mbFinalizePoints (int npts, int numExport, ZOLTAN_ID_PTR exportLocalIDs, int *exportProcs, int **assignment) |
int | mbInitializePoints (int npts, double *pts, int *ids, int *adjs, int *length, double *obj_weights=NULL, double *edge_weights=NULL, int *parts=NULL, bool part_geom=false) |
Private Attributes | |
Zoltan * | myZZ |
Range | partSets |
int | myNumPts |
int | argcArg |
char ** | argvArg |
Definition at line 109 of file ZoltanPartitioner.hpp.
ZoltanPartitioner::ZoltanPartitioner | ( | Interface * | impl = NULL , |
const bool | use_coords = false , |
||
int | argc = 0 , |
||
char ** | argv = NULL |
||
) |
Definition at line 71 of file ZoltanPartitioner.cpp.
: PartitionerBase< int >( impl, use_coords #ifdef MOAB_HAVE_MPI , parcomm #endif ), myZZ( NULL ), myNumPts( 0 ), argcArg( argc ), argvArg( argv ) #ifdef MOAB_HAVE_CGM , gti( gqt ) #endif { }
ZoltanPartitioner::~ZoltanPartitioner | ( | ) | [virtual] |
Definition at line 99 of file ZoltanPartitioner.cpp.
References myZZ.
ErrorCode ZoltanPartitioner::assemble_graph | ( | const int | dimension, |
std::vector< double > & | coords, | ||
std::vector< int > & | moab_ids, | ||
std::vector< int > & | adjacencies, | ||
std::vector< int > & | length, | ||
Range & | elems, | ||
bool | part_geom = false , |
||
const int | projection_type = 0 |
||
) | [private] |
Definition at line 801 of file ZoltanPartitioner.cpp.
References PartitionerBase< int >::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::Interface::globalId_tag(), moab::MAX_SUB_ENTITIES, MB_SUCCESS, PartitionerBase< int >::mbImpl, RR, moab::Range::size(), and moab::Interface::tag_get_data().
Referenced by balance_mesh(), and partition_mesh_and_geometry().
{ // 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; // assign global ids if( assign_global_ids ) { EntityHandle rootset = 0; result = mbpc->assign_global_ids( rootset, dimension, 1, true, true );RR; } // 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]; double avg_position[3]; int moab_id; // get the global id tag handle Tag gid = mbImpl->globalId_tag(); for( Range::iterator rit = elems.begin(); rit != elems.end(); ++rit ) { if( !part_geom ) { // get bridge adjacencies adjs.clear(); result = mtu.get_bridge_adjacencies( *rit, ( dimension > 0 ? dimension - 1 : 3 ), dimension, adjs );RR; // get the graph vertex ids of those if( !adjs.empty() ) { assert( adjs.size() < 5 * MAX_SUB_ENTITIES ); result = mbImpl->tag_get_data( gid, adjs, neighbors );RR; } // copy those into adjacencies vector length.push_back( (int)adjs.size() ); std::copy( neighbors, neighbors + adjs.size(), std::back_inserter( adjacencies ) ); } // get average position of vertices result = mtu.get_average_position( *rit, avg_position );RR; // get the graph vertex id for this element result = mbImpl->tag_get_data( gid, &( *rit ), 1, &moab_id );RR; // copy those into coords vector moab_ids.push_back( moab_id ); // transform coordinates to spherical coordinates, if requested if( projection_type > 0 ) IntxUtils::transform_coordinates( avg_position, projection_type ); 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< int >( std::cout, ", " ) ); std::cout << std::endl; std::cout << "Adjacencies vector: " << std::endl; std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< int >( std::cout, ", " ) ); std::cout << std::endl; std::cout << "Moab_ids vector: " << std::endl; std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< int >( 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 ZoltanPartitioner::balance_mesh | ( | const char * | zmethod, |
const char * | other_method, | ||
const bool | write_as_sets = true , |
||
const bool | write_as_tags = false |
||
) |
Definition at line 104 of file ZoltanPartitioner.cpp.
References argcArg, argvArg, assemble_graph(), ErrorCode, length(), MB_SUCCESS, mbFinalizePoints(), mbGetEdgeList(), mbGetNumberOfAssignedObjects(), mbGetNumberOfEdges(), mbGetObject(), mbGetObjectList(), mbGetObjectSize(), mbGlobalSuccess(), mbInitializePoints(), mbPrintGlobalResult(), myNumPts, myZZ, RR, SetHSFC_Parameters(), SetHypergraph_Parameters(), SetOCTPART_Parameters(), SetPARMETIS_Parameters(), SetRCB_Parameters(), SetRIB_Parameters(), and write_partition().
{ if( !strcmp( zmethod, "RR" ) && !strcmp( zmethod, "RCB" ) && !strcmp( zmethod, "RIB" ) && !strcmp( zmethod, "HSFC" ) && !strcmp( zmethod, "Hypergraph" ) && !strcmp( zmethod, "PHG" ) && !strcmp( zmethod, "PARMETIS" ) && !strcmp( zmethod, "OCTPART" ) ) { std::cout << "ERROR node " << mbpc->proc_config().proc_rank() << ": Method must be " << "RR, RCB, RIB, HSFC, Hypergraph (PHG), PARMETIS, or OCTPART" << std::endl; return MB_FAILURE; } std::vector< double > pts; // x[0], y[0], z[0], ... from MOAB std::vector< int > ids; // point ids from MOAB std::vector< int > adjs, length; Range elems; // Get a mesh from MOAB and divide it across processors. ErrorCode result; if( mbpc->proc_config().proc_rank() == 0 ) { result = assemble_graph( 3, pts, ids, adjs, length, elems );RR; } myNumPts = mbInitializePoints( (int)ids.size(), &pts[0], &ids[0], &adjs[0], &length[0] ); // Initialize Zoltan. This is a C call. The simple C++ code // that creates Zoltan objects does not keep track of whether // Zoltan_Initialize has been called. float version; Zoltan_Initialize( argcArg, argvArg, &version ); // Create Zoltan object. This calls Zoltan_Create. if( NULL == myZZ ) myZZ = new Zoltan( mbpc->comm() ); if( NULL == zmethod || !strcmp( zmethod, "RCB" ) ) SetRCB_Parameters(); else if( !strcmp( zmethod, "RIB" ) ) SetRIB_Parameters(); else if( !strcmp( zmethod, "HSFC" ) ) SetHSFC_Parameters(); else if( !strcmp( zmethod, "Hypergraph" ) || !strcmp( zmethod, "PHG" ) ) if( NULL == other_method ) SetHypergraph_Parameters( "auto" ); else SetHypergraph_Parameters( other_method ); else if( !strcmp( zmethod, "PARMETIS" ) ) { if( NULL == other_method ) SetPARMETIS_Parameters( "RepartGDiffusion" ); else SetPARMETIS_Parameters( other_method ); } else if( !strcmp( zmethod, "OCTPART" ) ) { if( NULL == other_method ) SetOCTPART_Parameters( "2" ); else SetOCTPART_Parameters( other_method ); } // Call backs: myZZ->Set_Num_Obj_Fn( mbGetNumberOfAssignedObjects, NULL ); myZZ->Set_Obj_List_Fn( mbGetObjectList, NULL ); myZZ->Set_Num_Geom_Fn( mbGetObjectSize, NULL ); myZZ->Set_Geom_Multi_Fn( mbGetObject, NULL ); myZZ->Set_Num_Edges_Multi_Fn( mbGetNumberOfEdges, NULL ); myZZ->Set_Edge_List_Multi_Fn( mbGetEdgeList, NULL ); // Perform the load balancing partitioning int changes; int numGidEntries; int numLidEntries; int numImport; ZOLTAN_ID_PTR importGlobalIds; ZOLTAN_ID_PTR importLocalIds; int* importProcs; int* importToPart; int numExport; ZOLTAN_ID_PTR exportGlobalIds; ZOLTAN_ID_PTR exportLocalIds; int* exportProcs; int* exportToPart; int rc = myZZ->LB_Partition( changes, numGidEntries, numLidEntries, numImport, importGlobalIds, importLocalIds, importProcs, importToPart, numExport, exportGlobalIds, exportLocalIds, exportProcs, exportToPart ); rc = mbGlobalSuccess( rc ); if( !rc ) { mbPrintGlobalResult( "==============Result==============", myNumPts, numImport, numExport, changes ); } else { return MB_FAILURE; } // take results & write onto MOAB partition sets int* assignment; mbFinalizePoints( (int)ids.size(), numExport, exportLocalIds, exportProcs, &assignment ); if( mbpc->proc_config().proc_rank() == 0 ) { result = write_partition( mbpc->proc_config().proc_size(), elems, assignment, write_as_sets, write_as_tags ); if( MB_SUCCESS != result ) return result; free( (int*)assignment ); } // Free the memory allocated for lists returned by LB_Parition() myZZ->LB_Free_Part( &importGlobalIds, &importLocalIds, &importProcs, &importToPart ); myZZ->LB_Free_Part( &exportGlobalIds, &exportLocalIds, &exportProcs, &exportToPart ); // Implementation note: A Zoltan object contains an MPI communicator. // When the Zoltan object is destroyed, it uses it's MPI communicator. // So it is important that the Zoltan object is destroyed before // the MPI communicator is destroyed. To ensure this, dynamically // allocate the Zoltan object, so you can explicitly destroy it. // If you create a Zoltan object on the stack, it's destructor will // be invoked atexit, possibly after the communicator's // destructor. return MB_SUCCESS; }
ErrorCode ZoltanPartitioner::include_closure | ( | ) | [virtual] |
Implements PartitionerBase< int >.
Definition at line 733 of file ZoltanPartitioner.cpp.
References moab::Interface::add_entities(), moab::Range::begin(), moab::Range::clear(), moab::Interface::dimension_from_handle(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::Range::find(), moab::Interface::get_adjacencies(), moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type(), moab::intersect(), MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< int >::mbImpl, partSets, RR, moab::Range::size(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), and smoab::UNION.
Referenced by main().
{ ErrorCode result; Range ents; Range adjs; std::cout << "Adding closure..." << std::endl; for( Range::iterator rit = partSets.begin(); rit != partSets.end(); ++rit ) { // get the top-dimensional entities in the part result = mbImpl->get_entities_by_handle( *rit, ents, true );RR; if( ents.empty() ) continue; // get intermediate-dimensional adjs and add to set for( int d = mbImpl->dimension_from_handle( *ents.begin() ) - 1; d >= 1; d-- ) { adjs.clear(); result = mbImpl->get_adjacencies( ents, d, false, adjs, Interface::UNION );RR; result = mbImpl->add_entities( *rit, adjs );RR; } // now get vertices and add to set; only need to do for ents, not for adjs adjs.clear(); result = mbImpl->get_adjacencies( ents, 0, false, adjs, Interface::UNION );RR; result = mbImpl->add_entities( *rit, adjs );RR; ents.clear(); } // now go over non-part entity sets, looking for contained entities Range sets, part_ents; result = mbImpl->get_entities_by_type( 0, MBENTITYSET, sets );RR; for( Range::iterator rit = sets.begin(); rit != sets.end(); ++rit ) { // skip parts if( partSets.find( *rit ) != partSets.end() ) continue; // get entities in this set, recursively ents.clear(); result = mbImpl->get_entities_by_handle( *rit, ents, true );RR; // now check over all parts for( Range::iterator rit2 = partSets.begin(); rit2 != partSets.end(); ++rit2 ) { part_ents.clear(); result = mbImpl->get_entities_by_handle( *rit2, part_ents, false );RR; Range int_range = intersect( ents, part_ents ); if( !int_range.empty() ) { // non-empty intersection, add to part set result = mbImpl->add_entities( *rit2, &( *rit ), 1 );RR; } } } // finally, mark all the part sets as having the closure Tag closure_tag; result = mbImpl->tag_get_handle( "INCLUDES_CLOSURE", 1, MB_TYPE_INTEGER, closure_tag, MB_TAG_SPARSE | MB_TAG_CREAT );RR; std::vector< int > closure_vals( partSets.size(), 1 ); result = mbImpl->tag_set_data( closure_tag, partSets, &closure_vals[0] );RR; return MB_SUCCESS; }
void ZoltanPartitioner::mbFinalizePoints | ( | int | npts, |
int | numExport, | ||
ZOLTAN_ID_PTR | exportLocalIDs, | ||
int * | exportProcs, | ||
int ** | assignment | ||
) | [private] |
Definition at line 1982 of file ZoltanPartitioner.cpp.
References NumPoints.
Referenced by balance_mesh().
{ int* MyAssignment; int i; int numPts; MPI_Status stat; int* recvA; /* assign pts to start */ if( mbpc->proc_config().proc_rank() == 0 ) MyAssignment = (int*)malloc( sizeof( int ) * npts ); else MyAssignment = (int*)malloc( sizeof( int ) * NumPoints ); for( i = 0; i < NumPoints; i++ ) MyAssignment[i] = mbpc->proc_config().proc_rank(); for( i = 0; i < numExport; i++ ) MyAssignment[exportLocalIDs[i]] = exportProcs[i]; if( mbpc->proc_config().proc_rank() == 0 ) { /* collect pts */ recvA = MyAssignment + NumPoints; for( i = 1; i < (int)mbpc->proc_config().proc_size(); i++ ) { MPI_Recv( &numPts, 1, MPI_INT, i, 0x04, mbpc->comm(), &stat ); MPI_Recv( recvA, numPts, MPI_INT, i, 0x05, mbpc->comm(), &stat ); recvA += numPts; } *assignment = MyAssignment; } else { MPI_Send( &NumPoints, 1, MPI_INT, 0, 0x04, mbpc->comm() ); MPI_Send( MyAssignment, NumPoints, MPI_INT, 0, 0x05, mbpc->comm() ); free( MyAssignment ); } }
int ZoltanPartitioner::mbGlobalSuccess | ( | int | rc | ) | [private] |
Definition at line 2029 of file ZoltanPartitioner.cpp.
References fail(), and mbShowError().
Referenced by balance_mesh().
{ int fail = 0; unsigned int i; int* vals = (int*)malloc( mbpc->proc_config().proc_size() * sizeof( int ) ); MPI_Allgather( &rc, 1, MPI_INT, vals, 1, MPI_INT, mbpc->comm() ); for( i = 0; i < mbpc->proc_config().proc_size(); i++ ) { if( vals[i] != ZOLTAN_OK ) { if( 0 == mbpc->proc_config().proc_rank() ) { mbShowError( vals[i], "Result on process " ); } fail = 1; } } free( vals ); return fail; }
int ZoltanPartitioner::mbInitializePoints | ( | int | npts, |
double * | pts, | ||
int * | ids, | ||
int * | adjs, | ||
int * | length, | ||
double * | obj_weights = NULL , |
||
double * | edge_weights = NULL , |
||
int * | parts = NULL , |
||
bool | part_geom = false |
||
) | [private] |
Definition at line 1862 of file ZoltanPartitioner.cpp.
References EdgeWeights, GlobalIds, length(), NborGlobalId, NborProcs, NumEdges, NumPoints, ObjWeights, Parts, Points, and moab::sum().
Referenced by balance_mesh(), and partition_mesh_and_geometry().
{ unsigned int i; int j; int *numPts, *nborProcs = NULL; int sum, ptsPerProc, ptsAssigned, mySize; MPI_Status stat; double* sendPts; int* sendIds; int* sendEdges = NULL; int* sendNborId = NULL; int* sendProcs; if( mbpc->proc_config().proc_rank() == 0 ) { /* divide pts to start */ numPts = (int*)malloc( sizeof( int ) * mbpc->proc_config().proc_size() ); ptsPerProc = npts / mbpc->proc_config().proc_size(); ptsAssigned = 0; for( i = 0; i < mbpc->proc_config().proc_size() - 1; i++ ) { numPts[i] = ptsPerProc; ptsAssigned += ptsPerProc; } numPts[mbpc->proc_config().proc_size() - 1] = npts - ptsAssigned; mySize = numPts[mbpc->proc_config().proc_rank()]; sendPts = pts + ( 3 * numPts[0] ); sendIds = ids + numPts[0]; sum = 0; // possible no adjacency sent if( !part_geom ) { sendEdges = length + numPts[0]; for( j = 0; j < numPts[0]; j++ ) sum += length[j]; sendNborId = adjs + sum; for( j = numPts[0]; j < npts; j++ ) sum += length[j]; nborProcs = (int*)malloc( sizeof( int ) * sum ); } for( j = 0; j < sum; j++ ) if( ( i = adjs[j] / ptsPerProc ) < mbpc->proc_config().proc_size() ) nborProcs[j] = i; else nborProcs[j] = mbpc->proc_config().proc_size() - 1; sendProcs = nborProcs + ( sendNborId - adjs ); for( i = 1; i < mbpc->proc_config().proc_size(); i++ ) { MPI_Send( &numPts[i], 1, MPI_INT, i, 0x00, mbpc->comm() ); MPI_Send( sendPts, 3 * numPts[i], MPI_DOUBLE, i, 0x01, mbpc->comm() ); MPI_Send( sendIds, numPts[i], MPI_INT, i, 0x03, mbpc->comm() ); MPI_Send( sendEdges, numPts[i], MPI_INT, i, 0x06, mbpc->comm() ); sum = 0; for( j = 0; j < numPts[i]; j++ ) sum += sendEdges[j]; MPI_Send( sendNborId, sum, MPI_INT, i, 0x07, mbpc->comm() ); MPI_Send( sendProcs, sum, MPI_INT, i, 0x08, mbpc->comm() ); sendPts += ( 3 * numPts[i] ); sendIds += numPts[i]; sendEdges += numPts[i]; sendNborId += sum; sendProcs += sum; } free( numPts ); } else { MPI_Recv( &mySize, 1, MPI_INT, 0, 0x00, mbpc->comm(), &stat ); pts = (double*)malloc( sizeof( double ) * 3 * mySize ); ids = (int*)malloc( sizeof( int ) * mySize ); length = (int*)malloc( sizeof( int ) * mySize ); if( obj_weights != NULL ) obj_weights = (double*)malloc( sizeof( double ) * mySize ); MPI_Recv( pts, 3 * mySize, MPI_DOUBLE, 0, 0x01, mbpc->comm(), &stat ); MPI_Recv( ids, mySize, MPI_INT, 0, 0x03, mbpc->comm(), &stat ); MPI_Recv( length, mySize, MPI_INT, 0, 0x06, mbpc->comm(), &stat ); sum = 0; for( j = 0; j < mySize; j++ ) sum += length[j]; adjs = (int*)malloc( sizeof( int ) * sum ); if( edge_weights != NULL ) edge_weights = (double*)malloc( sizeof( double ) * sum ); nborProcs = (int*)malloc( sizeof( int ) * sum ); MPI_Recv( adjs, sum, MPI_INT, 0, 0x07, mbpc->comm(), &stat ); MPI_Recv( nborProcs, sum, MPI_INT, 0, 0x08, mbpc->comm(), &stat ); } Points = pts; GlobalIds = ids; NumPoints = mySize; NumEdges = length; NborGlobalId = adjs; NborProcs = nborProcs; ObjWeights = obj_weights; EdgeWeights = edge_weights; Parts = parts; return mySize; }
void ZoltanPartitioner::mbPrintGlobalResult | ( | const char * | s, |
int | begin, | ||
int | import, | ||
int | exp, | ||
int | change | ||
) | [private] |
Definition at line 2053 of file ZoltanPartitioner.cpp.
Referenced by balance_mesh().
{ unsigned int i; int* v1 = (int*)malloc( 4 * sizeof( int ) ); int* v2 = NULL; int* v; v1[0] = begin; v1[1] = import; v1[2] = exp; v1[3] = change; if( mbpc->proc_config().proc_rank() == 0 ) { v2 = (int*)malloc( 4 * mbpc->proc_config().proc_size() * sizeof( int ) ); } MPI_Gather( v1, 4, MPI_INT, v2, 4, MPI_INT, 0, mbpc->comm() ); if( mbpc->proc_config().proc_rank() == 0 ) { fprintf( stdout, "======%s======\n", s ); for( i = 0, v = v2; i < mbpc->proc_config().proc_size(); i++, v += 4 ) { fprintf( stdout, "%u: originally had %d, import %d, exp %d, %s\n", i, v[0], v[1], v[2], v[3] ? "a change of partitioning" : "no change" ); } fprintf( stdout, "==========================================\n" ); fflush( stdout ); free( v2 ); } free( v1 ); }
void ZoltanPartitioner::mbShowError | ( | int | val, |
const char * | s | ||
) | [private] |
Definition at line 2089 of file ZoltanPartitioner.cpp.
Referenced by mbGlobalSuccess().
{ if( s ) printf( "%s ", s ); switch( val ) { case ZOLTAN_OK: printf( "%d: SUCCESSFUL\n", mbpc->proc_config().proc_rank() ); break; case ZOLTAN_WARN: printf( "%d: WARNING\n", mbpc->proc_config().proc_rank() ); break; case ZOLTAN_FATAL: printf( "%d: FATAL ERROR\n", mbpc->proc_config().proc_rank() ); break; case ZOLTAN_MEMERR: printf( "%d: MEMORY ALLOCATION ERROR\n", mbpc->proc_config().proc_rank() ); break; default: printf( "%d: INVALID RETURN CODE\n", mbpc->proc_config().proc_rank() ); break; } }
ErrorCode ZoltanPartitioner::partition_inferred_mesh | ( | EntityHandle | sfileset, |
size_t | num_parts, | ||
int | part_dim = 3 , |
||
const bool | write_as_sets = true , |
||
int | projection_type = 0 |
||
) |
Definition at line 356 of file ZoltanPartitioner.cpp.
References moab::Interface::add_entities(), moab::Interface::add_parent_child(), moab::Interface::create_meshset(), ErrorCode, moab::Interface::get_coords(), moab::Interface::get_entities_by_dimension(), moab::Interface::get_entities_by_type_and_tag(), MB_SUCCESS, MBENTITYSET, PartitionerBase< int >::mbImpl, MESHSET_SET, myZZ, moab::Interface::remove_entities(), RR, moab::Range::size(), moab::Interface::tag_set_data(), and smoab::UNION.
Referenced by main().
{ ErrorCode result; moab::Range elverts; result = mbImpl->get_entities_by_dimension( sfileset, part_dim, elverts );RR; std::vector< double > elcoords( elverts.size() * 3 ); result = mbImpl->get_coords( elverts, &elcoords[0] );RR; std::vector< std::vector< EntityHandle > > part_assignments( num_parts ); int part, proc; // Loop over coordinates for( size_t iel = 0; iel < elverts.size(); iel++ ) { // Gather coordinates into temporary array double* ecoords = &elcoords[iel * 3]; // do a projection if needed if( projection_type > 0 ) IntxUtils::transform_coordinates( ecoords, projection_type ); // Compute the coordinate's part assignment myZZ->LB_Point_PP_Assign( ecoords, proc, part ); // Store the part assignment in the return array part_assignments[part].push_back( elverts[iel] ); } // get the partition set tag Tag part_set_tag = mbpc->partition_tag(); // If some entity sets exist, let us delete those first. if( write_as_sets ) { moab::Range oldpsets; result = mbImpl->get_entities_by_type_and_tag( sfileset, MBENTITYSET, &part_set_tag, NULL, 1, oldpsets, Interface::UNION );RR; result = mbImpl->remove_entities( sfileset, oldpsets );RR; } size_t nparts_assigned = 0; for( size_t partnum = 0; partnum < num_parts; ++partnum ) { std::vector< EntityHandle >& partvec = part_assignments[partnum]; nparts_assigned += ( partvec.size() ? 1 : 0 ); if( write_as_sets ) { EntityHandle partNset; result = mbImpl->create_meshset( moab::MESHSET_SET, partNset );RR; if( partvec.size() ) { result = mbImpl->add_entities( partNset, &partvec[0], partvec.size() );RR; } result = mbImpl->add_parent_child( sfileset, partNset );RR; // part numbering should start from 0 int ipartnum = (int)partnum; // assign partitions as a sparse tag by grouping elements under sets result = mbImpl->tag_set_data( part_set_tag, &partNset, 1, &ipartnum );RR; } else { /* assign as a dense vector to all elements allocate integer-size partitions */ std::vector< int > assignment( partvec.size(), partnum ); // initialize all values to partnum result = mbImpl->tag_set_data( part_set_tag, &partvec[0], partvec.size(), &assignment[0] );RR; } } if( nparts_assigned != num_parts ) { std::cout << "WARNING: The inference yielded lesser number of parts (" << nparts_assigned << ") than requested by user (" << num_parts << ").\n"; } return MB_SUCCESS; }
ErrorCode ZoltanPartitioner::partition_mesh | ( | const int | 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 |
||
) | [inline, virtual] |
Implements PartitionerBase< int >.
Definition at line 298 of file ZoltanPartitioner.hpp.
{ return partition_mesh_and_geometry( -1.0, nparts, method, NULL, 1.03, part_dim, write_as_sets, write_as_tags, 0, 0, false, false, 0, false, print_time ); }
ErrorCode ZoltanPartitioner::partition_mesh_and_geometry | ( | const double | part_geom_mesh_size, |
const int | 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] |
Implements PartitionerBase< int >.
Definition at line 443 of file ZoltanPartitioner.cpp.
References argcArg, argvArg, assemble_graph(), moab::debug, moab::Range::empty(), entities, ErrorCode, moab::Interface::get_entities_by_dimension(), length(), MB_SUCCESS, mbGetEdgeList(), mbGetNumberOfAssignedObjects(), mbGetNumberOfEdges(), mbGetObject(), mbGetObjectList(), mbGetObjectSize(), mbGetPart(), PartitionerBase< int >::mbImpl, mbInitializePoints(), myNumPts, myZZ, nparts, RR, SetHSFC_Parameters(), SetHypergraph_Parameters(), SetOCTPART_Parameters(), SetPARMETIS_Parameters(), SetRCB_Parameters(), SetRIB_Parameters(), moab::Range::size(), t, and write_partition().
Referenced by main().
{ // should only be called in serial if( mbpc->proc_config().proc_size() != 1 ) { std::cout << "ZoltanPartitioner::partition_mesh_and_geometry must be called in serial." << std::endl; return MB_FAILURE; } clock_t t = clock(); if( NULL != zmethod && strcmp( zmethod, "RR" ) && strcmp( zmethod, "RCB" ) && strcmp( zmethod, "RIB" ) && strcmp( zmethod, "HSFC" ) && strcmp( zmethod, "Hypergraph" ) && strcmp( zmethod, "PHG" ) && strcmp( zmethod, "PARMETIS" ) && strcmp( zmethod, "OCTPART" ) ) { std::cout << "ERROR node " << mbpc->proc_config().proc_rank() << ": Method must be " << "RCB, RIB, HSFC, Hypergraph (PHG), PARMETIS, or OCTPART" << std::endl; return MB_FAILURE; } bool part_geom = false; if( 0 == strcmp( zmethod, "RR" ) || 0 == strcmp( zmethod, "RCB" ) || 0 == strcmp( zmethod, "RIB" ) || 0 == strcmp( zmethod, "HSFC" ) ) part_geom = true; // so no adjacency / edges needed std::vector< double > pts; // x[0], y[0], z[0], ... from MOAB std::vector< int > ids; // point ids from MOAB std::vector< int > adjs, length, parts; std::vector< double > obj_weights, edge_weights; Range elems; #ifdef MOAB_HAVE_CGM DLIList< RefEntity* > entities; #endif // Get a mesh from MOAB and diide it across processors. ErrorCode result = MB_SUCCESS; // short-circuit everything if RR partition is requested if( !strcmp( zmethod, "RR" ) ) { if( part_geom_mesh_size < 0. ) { // get all elements result = mbImpl->get_entities_by_dimension( 0, part_dim, elems );RR; if( elems.empty() ) return MB_FAILURE; // make a trivial assignment vector std::vector< int > assign_vec( elems.size() ); int num_per = elems.size() / nparts; int extra = elems.size() % nparts; if( extra ) num_per++; int nstart = 0; for( int i = 0; i < nparts; i++ ) { if( i == extra ) num_per--; std::fill( &assign_vec[nstart], &assign_vec[nstart + num_per], i ); nstart += num_per; } result = write_partition( nparts, elems, &assign_vec[0], write_as_sets, write_as_tags );RR; } else { #ifdef MOAB_HAVE_CGM result = partition_round_robin( nparts );RR; #endif } return result; } std::cout << "Assembling graph..." << std::endl; if( part_geom_mesh_size < 0. ) { // if (!part_geom) { result = assemble_graph( part_dim, pts, ids, adjs, length, elems, part_geom, projection_type );RR; } else { #ifdef MOAB_HAVE_CGM result = assemble_graph( part_dim, pts, ids, adjs, length, obj_weights, edge_weights, parts, entities, part_geom_mesh_size, nparts );RR; if( debug ) { int n_ids = ids.size(); entities.reset(); int i_leng = 0; for( int i = 0; i < n_ids; i++ ) { std::cout << "graph_input_ids[" << i << "]=" << ids[i] << ",obj_weights=" << obj_weights[i] << ",entity_id=" << entities.get_and_step()->id() << ",part=" << parts[i] << std::endl; for( int j = 0; j < length[i]; j++ ) { std::cout << "adjs[" << j << "]=" << adjs[i_leng] << ",edge_weights=" << edge_weights[i_leng] << std::endl; i_leng++; } } } #endif } if( print_time ) { std::cout << " time to assemble graph: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n"; t = clock(); } double* o_wgt = NULL; double* e_wgt = NULL; if( obj_weights.size() > 0 ) o_wgt = &obj_weights[0]; if( edge_weights.size() > 0 ) e_wgt = &edge_weights[0]; myNumPts = mbInitializePoints( (int)ids.size(), &pts[0], &ids[0], &adjs[0], &length[0], o_wgt, e_wgt, &parts[0], part_geom ); // Initialize Zoltan. This is a C call. The simple C++ code // that creates Zoltan objects does not keep track of whether // Zoltan_Initialize has been called. if( print_time ) { std::cout << " time to initialize points: " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n"; t = clock(); } float version; std::cout << "Initializing zoltan..." << std::endl; Zoltan_Initialize( argcArg, argvArg, &version ); // Create Zoltan object. This calls Zoltan_Create. if( NULL == myZZ ) myZZ = new Zoltan( mbpc->comm() ); if( NULL == zmethod || !strcmp( zmethod, "RCB" ) ) { if( projection_type == 2 ) SetRCB_Parameters( true ); else SetRCB_Parameters( recompute_rcb_box ); } else if( !strcmp( zmethod, "RIB" ) ) SetRIB_Parameters(); else if( !strcmp( zmethod, "HSFC" ) ) SetHSFC_Parameters(); else if( !strcmp( zmethod, "Hypergraph" ) || !strcmp( zmethod, "PHG" ) ) { if( NULL == other_method || ( other_method[0] == '\0' ) ) SetHypergraph_Parameters( "auto" ); else SetHypergraph_Parameters( other_method ); if( imbal_tol ) { std::ostringstream str; str << imbal_tol; myZZ->Set_Param( "IMBALANCE_TOL", str.str().c_str() ); // no debug messages } } else if( !strcmp( zmethod, "PARMETIS" ) ) { if( NULL == other_method ) SetPARMETIS_Parameters( "RepartGDiffusion" ); else SetPARMETIS_Parameters( other_method ); } else if( !strcmp( zmethod, "OCTPART" ) ) { if( NULL == other_method ) SetOCTPART_Parameters( "2" ); else SetOCTPART_Parameters( other_method ); } // set # requested partitions char buff[10]; sprintf( buff, "%d", nparts ); int retval = myZZ->Set_Param( "NUM_GLOBAL_PARTITIONS", buff ); if( ZOLTAN_OK != retval ) return MB_FAILURE; // request only partition assignments retval = myZZ->Set_Param( "RETURN_LISTS", "PARTITION ASSIGNMENTS" ); if( ZOLTAN_OK != retval ) return MB_FAILURE; if( obj_weight > 0 ) { std::ostringstream str; str << obj_weight; retval = myZZ->Set_Param( "OBJ_WEIGHT_DIM", str.str().c_str() ); if( ZOLTAN_OK != retval ) return MB_FAILURE; } if( edge_weight > 0 ) { std::ostringstream str; str << edge_weight; retval = myZZ->Set_Param( "EDGE_WEIGHT_DIM", str.str().c_str() ); if( ZOLTAN_OK != retval ) return MB_FAILURE; } // Call backs: myZZ->Set_Num_Obj_Fn( mbGetNumberOfAssignedObjects, NULL ); myZZ->Set_Obj_List_Fn( mbGetObjectList, NULL ); myZZ->Set_Num_Geom_Fn( mbGetObjectSize, NULL ); myZZ->Set_Geom_Multi_Fn( mbGetObject, NULL ); myZZ->Set_Num_Edges_Multi_Fn( mbGetNumberOfEdges, NULL ); myZZ->Set_Edge_List_Multi_Fn( mbGetEdgeList, NULL ); if( part_geom_mesh_size > 0. ) { myZZ->Set_Part_Multi_Fn( mbGetPart, NULL ); } // Perform the load balancing partitioning int changes; int numGidEntries; int numLidEntries; int dumnum1; ZOLTAN_ID_PTR dum_local, dum_global; int *dum1, *dum2; int num_assign; ZOLTAN_ID_PTR assign_gid, assign_lid; int *assign_procs, *assign_parts; std::cout << "Computing partition using " << ( zmethod ? zmethod : "RCB" ) << " method for " << nparts << " processors..." << std::endl; #ifndef NDEBUG #if 0 if (NULL == zmethod || !strcmp(zmethod, "RCB")) Zoltan_Generate_Files(myZZ->Get_C_Handle(), (char*)zmethod, 1, 1, 0, 0); if ( !strcmp(zmethod, "PHG")) Zoltan_Generate_Files(myZZ->Get_C_Handle(), (char*)zmethod, 1, 0, 1, 1); #endif #endif retval = myZZ->LB_Partition( changes, numGidEntries, numLidEntries, dumnum1, dum_global, dum_local, dum1, dum2, num_assign, assign_gid, assign_lid, assign_procs, assign_parts ); if( ZOLTAN_OK != retval ) return MB_FAILURE; if( print_time ) { std::cout << " time to LB_partition " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n"; t = clock(); } // take results & write onto MOAB partition sets std::cout << "Saving partition information to MOAB..." << std::endl; if( part_geom_mesh_size < 0. ) { // if (!part_geom) { result = write_partition( nparts, elems, assign_parts, write_as_sets, write_as_tags ); } else { #ifdef MOAB_HAVE_CGM result = write_partition( nparts, entities, assign_parts, obj_weights, part_surf, ghost ); #endif } if( print_time ) { std::cout << " time to write partition in memory " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n"; t = clock(); } if( MB_SUCCESS != result ) return result; // Free the memory allocated for lists returned by LB_Parition() myZZ->LB_Free_Part( &assign_gid, &assign_lid, &assign_procs, &assign_parts ); return MB_SUCCESS; }
ErrorCode ZoltanPartitioner::partition_owned_cells | ( | Range & | owned, |
std::multimap< int, int > & | extraGraphEdges, | ||
std::map< int, int > | procs, | ||
int & | numNewPartitions, | ||
std::map< int, Range > & | distribution, | ||
int | met, | ||
std::vector< char > & | ZoltanBuffer | ||
) |
Definition at line 2280 of file ZoltanPartitioner.cpp.
References argcArg, argvArg, moab::Range::begin(), moab::Range::clear(), moab::Interface::dimension_from_handle(), EdgeWeights, moab::Range::empty(), moab::Range::end(), ErrorCode, moab::MeshTopoUtil::get_average_position(), moab::MeshTopoUtil::get_bridge_adjacencies(), moab::Interface::get_coords(), moab::Interface::globalId_tag(), GlobalIds, length(), moab::MAX_SUB_ENTITIES, MB_CHK_ERR, MB_SUCCESS, mbGetEdgeList(), mbGetNumberOfAssignedObjects(), mbGetNumberOfEdges(), mbGetObject(), mbGetObjectList(), mbGetObjectSize(), PartitionerBase< int >::mbImpl, MBVERTEX, myZZ, NborGlobalId, NborProcs, NumEdges, NumPoints, ObjWeights, Parts, Points, moab::Range::rbegin(), SetHypergraph_Parameters(), SetRCB_Parameters(), moab::Range::size(), moab::Interface::tag_get_data(), and moab::TYPE_FROM_HANDLE().
Referenced by moab::ParCommGraph::compute_partition().
{ // start copy MeshTopoUtil mtu( mbImpl ); Range adjs; std::vector< int > adjacencies; std::vector< int > ids; ids.resize( primary.size() ); std::vector< int > length; std::vector< double > coords; std::vector< int > nbor_proc; // can use a fixed-size array 'cuz the number of lower-dimensional neighbors is limited // by MBCN int neighbors[5 * MAX_SUB_ENTITIES]; int neib_proc[5 * MAX_SUB_ENTITIES]; double avg_position[3]; int moab_id; int primaryDim = mbImpl->dimension_from_handle( *primary.rbegin() ); // get the global id tag handle Tag gid = mbImpl->globalId_tag(); ErrorCode rval = mbImpl->tag_get_data( gid, primary, &ids[0] );MB_CHK_ERR( rval ); // mbpc is member in base class, PartitionerBase int rank = mbpc->rank(); // current rank , will be put on regular neighbors int i = 0; for( Range::iterator rit = primary.begin(); rit != primary.end(); ++rit, i++ ) { EntityHandle cell = *rit; // get bridge adjacencies for each cell if( 1 == met ) { adjs.clear(); rval = mtu.get_bridge_adjacencies( cell, ( primaryDim > 0 ? primaryDim - 1 : 3 ), primaryDim, adjs );MB_CHK_ERR( rval ); // get the graph vertex ids of those if( !adjs.empty() ) { assert( adjs.size() < 5 * MAX_SUB_ENTITIES ); rval = mbImpl->tag_get_data( gid, adjs, neighbors );MB_CHK_ERR( rval ); } // if adjacent to neighbor partitions, add to the list int size_adjs = (int)adjs.size(); moab_id = ids[i]; for( int k = 0; k < size_adjs; k++ ) neib_proc[k] = rank; // current rank if( extraGraphEdges.find( moab_id ) != extraGraphEdges.end() ) { // it means that the current cell is adjacent to a cell in another partition ; maybe // a few std::pair< std::multimap< int, int >::iterator, std::multimap< int, int >::iterator > ret; ret = extraGraphEdges.equal_range( moab_id ); for( std::multimap< int, int >::iterator it = ret.first; it != ret.second; ++it ) { int otherID = it->second; neighbors[size_adjs] = otherID; // the id of the other cell, across partition neib_proc[size_adjs] = procs[otherID]; // this is how we built this map, the cell id maps to // what proc it came from size_adjs++; } } // copy those into adjacencies vector length.push_back( size_adjs ); std::copy( neighbors, neighbors + size_adjs, std::back_inserter( adjacencies ) ); std::copy( neib_proc, neib_proc + size_adjs, std::back_inserter( nbor_proc ) ); } else if( 2 <= met ) // include 2 RCB or 3, RCB + gnomonic projection { if( TYPE_FROM_HANDLE( cell ) == MBVERTEX ) { rval = mbImpl->get_coords( &cell, 1, avg_position );MB_CHK_ERR( rval ); } else { rval = mtu.get_average_position( cell, avg_position );MB_CHK_ERR( rval ); } if( 3 <= met ) { IntxUtils::transform_coordinates( avg_position, 2 ); // 2 means gnomonic projection } std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) ); } } #ifdef VERBOSE std::stringstream ff2; ff2 << "zoltanInput_" << mbpc->rank() << ".txt"; std::ofstream ofs; ofs.open( ff2.str().c_str(), std::ofstream::out ); ofs << "Length vector: " << std::endl; std::copy( length.begin(), length.end(), std::ostream_iterator< int >( ofs, ", " ) ); ofs << std::endl; ofs << "Adjacencies vector: " << std::endl; std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< int >( ofs, ", " ) ); ofs << std::endl; ofs << "Moab_ids vector: " << std::endl; std::copy( ids.begin(), ids.end(), std::ostream_iterator< int >( ofs, ", " ) ); ofs << std::endl; ofs << "Coords vector: " << std::endl; std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( ofs, ", " ) ); ofs << std::endl; ofs.close(); #endif // these are static var in this file, and used in the callbacks Points = NULL; if( 1 != met ) Points = &coords[0]; GlobalIds = &ids[0]; NumPoints = (int)ids.size(); NumEdges = &length[0]; NborGlobalId = &adjacencies[0]; NborProcs = &nbor_proc[0]; ObjWeights = NULL; EdgeWeights = NULL; Parts = NULL; float version; if( mbpc->rank() == 0 ) std::cout << "Initializing zoltan..." << std::endl; Zoltan_Initialize( argcArg, argvArg, &version ); // Create Zoltan object. This calls Zoltan_Create. // old code if( met <= 4 ) { if( NULL == myZZ ) myZZ = new Zoltan( mbpc->comm() ); // set # requested partitions char buff[10]; sprintf( buff, "%d", numNewPartitions ); int retval = myZZ->Set_Param( "NUM_GLOBAL_PARTITIONS", buff ); if( ZOLTAN_OK != retval ) return MB_FAILURE; // request parts assignment retval = myZZ->Set_Param( "RETURN_LISTS", "PARTS" ); if( ZOLTAN_OK != retval ) return MB_FAILURE; myZZ->Set_Num_Obj_Fn( mbGetNumberOfAssignedObjects, NULL ); myZZ->Set_Obj_List_Fn( mbGetObjectList, NULL ); // due to a bug in zoltan, if method is graph partitioning, do not pass coordinates!! if( 2 <= met ) { myZZ->Set_Num_Geom_Fn( mbGetObjectSize, NULL ); myZZ->Set_Geom_Multi_Fn( mbGetObject, NULL ); if( 3 <= met ) SetRCB_Parameters( /*const bool recompute_rcb_box*/ true ); // recompute rcb box else SetRCB_Parameters( /*const bool recompute_rcb_box*/ false ); // recompute rcb box // is it faster ? } else if( 1 == met ) { myZZ->Set_Num_Edges_Multi_Fn( mbGetNumberOfEdges, NULL ); myZZ->Set_Edge_List_Multi_Fn( mbGetEdgeList, NULL ); SetHypergraph_Parameters( "auto" ); } // Perform the load balancing partitioning int changes; int numGidEntries; int numLidEntries; int num_import; ZOLTAN_ID_PTR import_global_ids, import_local_ids; int* import_procs; int* import_to_part; int num_export; ZOLTAN_ID_PTR export_global_ids, export_local_ids; int *assign_procs, *assign_parts; if( mbpc->rank() == 0 ) std::cout << "Computing partition using method (1-graph, 2-geom):" << met << " for " << numNewPartitions << " parts..." << std::endl; #ifndef NDEBUG #if 0 static int counter=0; // it may be possible to call function multiple times in a simulation // give a way to not overwrite the files // it should work only with a modified version of Zoltan std::stringstream basename; if (1==met) { basename << "phg_" << counter++; Zoltan_Generate_Files(myZZ->Get_C_Handle(), (char*)(basename.str().c_str()), 1, 0, 1, 0); } else if (2==met) { basename << "rcb_" << counter++; Zoltan_Generate_Files(myZZ->Get_C_Handle(), (char*)(basename.str().c_str()), 1, 1, 0, 0); } #endif #endif retval = myZZ->LB_Partition( changes, numGidEntries, numLidEntries, num_import, import_global_ids, import_local_ids, import_procs, import_to_part, num_export, export_global_ids, export_local_ids, assign_procs, assign_parts ); if( ZOLTAN_OK != retval ) return MB_FAILURE; #ifdef VERBOSE std::stringstream ff3; ff3 << "zoltanOutput_" << mbpc->rank() << ".txt"; std::ofstream ofs3; ofs3.open( ff3.str().c_str(), std::ofstream::out ); ofs3 << " export elements on rank " << rank << " \n"; ofs3 << "\t index \t gb_id \t local \t proc \t part \n"; for( int k = 0; k < num_export; k++ ) { ofs3 << "\t" << k << "\t" << export_global_ids[k] << "\t" << export_local_ids[k] << "\t" << assign_procs[k] << "\t" << assign_parts[k] << "\n"; } ofs3.close(); #endif // basically each local cell is assigned to a part // new code: if method == 4, we need to serialize, and send it to root of the coupler // here, we serialize it; sending it will happen in the calling method, where we have access to // the root of the coupler, which will store the buffer if( 4 == met ) { if( 0 == rank ) { size_t bufSize = myZZ->Serialize_Size(); /* Then allocate the buffer */ ZoltanBuffer.resize( bufSize ); int ierr = myZZ->Serialize( bufSize, &ZoltanBuffer[0] ); if( ierr != 0 ) MB_CHK_ERR( MB_FAILURE ); } } assert( num_export == (int)primary.size() ); for( i = 0; i < num_export; i++ ) { EntityHandle cell = primary[export_local_ids[i]]; distribution[assign_parts[i]].insert( cell ); } Zoltan::LB_Free_Part( &import_global_ids, &import_local_ids, &import_procs, &import_to_part ); Zoltan::LB_Free_Part( &export_global_ids, &export_local_ids, &assign_procs, &assign_parts ); delete myZZ; myZZ = NULL; } else if( 5 == met ) { if( NULL == myZZ ) myZZ = new Zoltan( mbpc->comm() ); // zoltan buffer is only on rank 0 right now // broadcast it first: int rank = mbpc->rank(); size_t bufSize; if( rank == 0 ) bufSize = ZoltanBuffer.size(); MPI_Bcast( (char*)&bufSize, sizeof( bufSize ), MPI_CHAR, 0, mbpc->comm() ); if( 0 != rank ) ZoltanBuffer.resize( bufSize ); MPI_Bcast( &ZoltanBuffer[0], bufSize, MPI_CHAR, 0, mbpc->comm() ); // deserialize on each task int ierr = myZZ->Deserialize( ZoltanBuffer.size(), &ZoltanBuffer[0] ); if( ierr != 0 ) MB_CHK_ERR( MB_FAILURE ); // use here the partitioning !! /* code in inferred partitions: // Compute the coordinate's part assignment myZZ->LB_Point_PP_Assign( ecoords, proc, part ); // Store the part assignment in the return array part_assignments[part].push_back( elverts[iel] );*/ i = 0; for( Range::iterator rit = primary.begin(); rit != primary.end(); ++rit, i++ ) { EntityHandle cell = *rit; int proc = 0, part = 0; // coords are calculated in advance, contain the centers of the cells, maybe in gnomonic plane myZZ->LB_Point_PP_Assign( &coords[3 * i], proc, part ); distribution[part].insert( cell ); } // TODO delete myZZ; myZZ = NULL; } // clear arrays that were resized locally, to free up local memory std::vector< int >().swap( adjacencies ); std::vector< int >().swap( ids ); std::vector< int >().swap( length ); std::vector< int >().swap( nbor_proc ); std::vector< double >().swap( coords ); return MB_SUCCESS; }
ErrorCode ZoltanPartitioner::repartition | ( | std::vector< double > & | x, |
std::vector< double > & | y, | ||
std::vector< double > & | z, | ||
int | StartID, | ||
const char * | zmethod, | ||
Range & | localGIDs | ||
) |
Definition at line 243 of file ZoltanPartitioner.cpp.
References argcArg, argvArg, EdgeWeights, GlobalIds, MB_SUCCESS, mbGetEdgeList(), mbGetNumberOfAssignedObjects(), mbGetNumberOfEdges(), mbGetObject(), mbGetObjectList(), mbGetObjectSize(), myZZ, NborGlobalId, NborProcs, NumEdges, NumPoints, ObjWeights, Parts, Points, SetHSFC_Parameters(), SetRCB_Parameters(), SetRIB_Parameters(), moab::subtract(), t, and moab::unite().
Referenced by moab::NCHelperScrip::create_mesh().
{ // int nprocs = mbpc->proc_config().proc_size(); int rank = mbpc->proc_config().proc_rank(); clock_t t = clock(); // form pts and ids, as in assemble_graph std::vector< double > pts; // x[0], y[0], z[0], ... from MOAB pts.resize( x.size() * 3 ); std::vector< int > ids; // point ids from MOAB ids.resize( x.size() ); for( size_t i = 0; i < x.size(); i++ ) { pts[3 * i] = x[i]; pts[3 * i + 1] = y[i]; pts[3 * i + 2] = z[i]; ids[i] = StartID + (int)i; } // do not get out until done! Points = &pts[0]; GlobalIds = &ids[0]; NumPoints = (int)x.size(); NumEdges = NULL; NborGlobalId = NULL; NborProcs = NULL; ObjWeights = NULL; EdgeWeights = NULL; Parts = NULL; float version; if( rank == 0 ) std::cout << "Initializing zoltan..." << std::endl; Zoltan_Initialize( argcArg, argvArg, &version ); // Create Zoltan object. This calls Zoltan_Create. if( NULL == myZZ ) myZZ = new Zoltan( mbpc->comm() ); if( NULL == zmethod || !strcmp( zmethod, "RCB" ) ) SetRCB_Parameters(); else if( !strcmp( zmethod, "RIB" ) ) SetRIB_Parameters(); else if( !strcmp( zmethod, "HSFC" ) ) SetHSFC_Parameters(); // set # requested partitions char buff[10]; sprintf( buff, "%d", nprocs ); int retval = myZZ->Set_Param( "NUM_GLOBAL_PARTITIONS", buff ); if( ZOLTAN_OK != retval ) return MB_FAILURE; // request all, import and export retval = myZZ->Set_Param( "RETURN_LISTS", "ALL" ); if( ZOLTAN_OK != retval ) return MB_FAILURE; myZZ->Set_Num_Obj_Fn( mbGetNumberOfAssignedObjects, NULL ); myZZ->Set_Obj_List_Fn( mbGetObjectList, NULL ); myZZ->Set_Num_Geom_Fn( mbGetObjectSize, NULL ); myZZ->Set_Geom_Multi_Fn( mbGetObject, NULL ); myZZ->Set_Num_Edges_Multi_Fn( mbGetNumberOfEdges, NULL ); myZZ->Set_Edge_List_Multi_Fn( mbGetEdgeList, NULL ); // Perform the load balancing partitioning int changes; int numGidEntries; int numLidEntries; int num_import; ZOLTAN_ID_PTR import_global_ids, import_local_ids; int* import_procs; int* import_to_part; int num_export; ZOLTAN_ID_PTR export_global_ids, export_local_ids; int *assign_procs, *assign_parts; if( rank == 0 ) std::cout << "Computing partition using " << ( zmethod ? zmethod : "RCB" ) << " method for " << nprocs << " processors..." << std::endl; retval = myZZ->LB_Partition( changes, numGidEntries, numLidEntries, num_import, import_global_ids, import_local_ids, import_procs, import_to_part, num_export, export_global_ids, export_local_ids, assign_procs, assign_parts ); if( ZOLTAN_OK != retval ) return MB_FAILURE; if( rank == 0 ) { std::cout << " time to LB_partition " << ( clock() - t ) / (double)CLOCKS_PER_SEC << "s. \n"; t = clock(); } std::sort( import_global_ids, import_global_ids + num_import, std::greater< int >() ); std::sort( export_global_ids, export_global_ids + num_export, std::greater< int >() ); Range iniGids( (EntityHandle)StartID, (EntityHandle)StartID + x.size() - 1 ); Range imported, exported; std::copy( import_global_ids, import_global_ids + num_import, range_inserter( imported ) ); std::copy( export_global_ids, export_global_ids + num_export, range_inserter( exported ) ); localGIDs = subtract( iniGids, exported ); localGIDs = unite( localGIDs, imported ); // Free data structures allocated by Zoltan::LB_Partition retval = myZZ->LB_Free_Part( &import_global_ids, &import_local_ids, &import_procs, &import_to_part ); if( ZOLTAN_OK != retval ) return MB_FAILURE; retval = myZZ->LB_Free_Part( &export_global_ids, &export_local_ids, &assign_procs, &assign_parts ); if( ZOLTAN_OK != retval ) return MB_FAILURE; return MB_SUCCESS; }
Definition at line 1810 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), partition_mesh_and_geometry(), and repartition().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nHilbert Space Filling Curve" << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "HSFC" ); // perform Hilbert space filling curve // HSFC parameters: myZZ->Set_Param( "KEEP_CUTS", "1" ); // save decomposition }
void ZoltanPartitioner::SetHypergraph_Parameters | ( | const char * | phg_method | ) |
Definition at line 1823 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), partition_mesh_and_geometry(), and partition_owned_cells().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nHypergraph (or PHG): " << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "Hypergraph" ); // Hypergraph (or PHG) // Hypergraph (or PHG) parameters: myZZ->Set_Param( "PHG_COARSEPARTITION_METHOD", phg_method ); // CoarsePartitionMethod }
void ZoltanPartitioner::SetOCTPART_Parameters | ( | const char * | oct_method | ) |
Definition at line 1848 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), and partition_mesh_and_geometry().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nOctree Partitioning: " << oct_method << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "OCTPART" ); // octree partitioning // OCTPART parameters: myZZ->Set_Param( "OCT_METHOD", oct_method ); // the SFC to be used myZZ->Set_Param( "OCT_OUTPUT_LEVEL", "3" ); }
void ZoltanPartitioner::SetPARMETIS_Parameters | ( | const char * | parmetis_method | ) |
Definition at line 1835 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), and partition_mesh_and_geometry().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nPARMETIS: " << parmetis_method << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "PARMETIS" ); // the ParMETIS library // PARMETIS parameters: myZZ->Set_Param( "PARMETIS_METHOD", parmetis_method ); // method in the library }
void ZoltanPartitioner::SetRCB_Parameters | ( | const bool | recompute_rcb_box = false | ) |
Definition at line 1779 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), partition_mesh_and_geometry(), partition_owned_cells(), and repartition().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nRecursive Coordinate Bisection" << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "RCB" ); // recursive coordinate bisection // myZZ->Set_Param( "RCB_RECOMPUTE_BOX", "1" ); // recompute RCB box if needed ? // RCB parameters: myZZ->Set_Param( "RCB_OUTPUT_LEVEL", "1" ); myZZ->Set_Param( "KEEP_CUTS", "1" ); // save decomposition so that we can infer partitions // myZZ->Set_Param("RCB_RECTILINEAR_BLOCKS", "1"); // don't split point on boundary if( recompute_rcb_box ) myZZ->Set_Param( "RCB_RECOMPUTE_BOX", "1" ); }
void ZoltanPartitioner::SetRIB_Parameters | ( | ) |
Definition at line 1796 of file ZoltanPartitioner.cpp.
References myZZ.
Referenced by balance_mesh(), partition_mesh_and_geometry(), and repartition().
{ if( mbpc->proc_config().proc_rank() == 0 ) std::cout << "\nRecursive Inertial Bisection" << std::endl; // General parameters: myZZ->Set_Param( "DEBUG_LEVEL", "0" ); // no debug messages myZZ->Set_Param( "LB_METHOD", "RIB" ); // Recursive Inertial Bisection // RIB parameters: myZZ->Set_Param( "KEEP_CUTS", "1" ); // save decomposition myZZ->Set_Param( "AVERAGE_CUTS", "1" ); }
ErrorCode ZoltanPartitioner::write_partition | ( | const int | nparts, |
Range & | elems, | ||
const int * | assignment, | ||
const bool | write_as_sets, | ||
const bool | write_as_tags | ||
) | [virtual] |
Definition at line 1665 of file ZoltanPartitioner.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_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, PartitionerBase< int >::mbImpl, MESHSET_SET, nparts, partSets, moab::Range::pop_back(), RR, 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 balance_mesh(), and partition_mesh_and_geometry().
{ ErrorCode result; // get the partition set tag Tag part_set_tag; int 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 );RR; // 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 );RR; if( !tagged_sets.empty() ) { result = mbImpl->clear_meshset( tagged_sets );RR; if( !write_as_sets ) { result = mbImpl->tag_delete_data( part_set_tag, tagged_sets );RR; } } 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 int num_new = nparts - tagged_sets.size(); for( i = 0; i < num_new; i++ ) { EntityHandle new_set; result = mbImpl->create_meshset( MESHSET_SET, new_set );RR; tagged_sets.insert( new_set ); } } else if( nparts < (int)tagged_sets.size() ) { // too many partition sets - delete extras int 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 );RR; } } // 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]; for( i = 0; i < nparts; i++ ) dum_ids[i] = i; result = mbImpl->tag_set_data( part_set_tag, partSets, dum_ids );RR; // found out by valgrind when we run mbpart delete[] dum_ids; dum_ids = NULL; // assign entities to the relevant sets std::vector< EntityHandle > tmp_part_sets; // int N = (int)elems.size(); std::copy( partSets.begin(), partSets.end(), std::back_inserter( tmp_part_sets ) ); /*Range::reverse_iterator riter; for (i = N-1, riter = elems.rbegin(); riter != elems.rend(); ++riter, i--) { int assigned_part = assignment[i]; part_ranges[assigned_part].insert(*riter); //result = mbImpl->add_entities(tmp_part_sets[assignment[i]], &(*rit), 1); RR; }*/ 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 );RR; } /*for (i=0; i<nparts; i++) { result = mbImpl->add_entities(tmp_part_sets[i], part_ranges[i]); RR; } delete [] part_ranges;*/ // 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 ) { // allocate integer-size partitions result = mbImpl->tag_set_data( part_set_tag, elems, assignment );RR; } return MB_SUCCESS; }
int ZoltanPartitioner::argcArg [private] |
Definition at line 234 of file ZoltanPartitioner.hpp.
Referenced by balance_mesh(), partition_mesh_and_geometry(), partition_owned_cells(), and repartition().
char** ZoltanPartitioner::argvArg [private] |
Definition at line 236 of file ZoltanPartitioner.hpp.
Referenced by balance_mesh(), partition_mesh_and_geometry(), partition_owned_cells(), and repartition().
int ZoltanPartitioner::myNumPts [private] |
Definition at line 232 of file ZoltanPartitioner.hpp.
Referenced by balance_mesh(), and partition_mesh_and_geometry().
Zoltan* ZoltanPartitioner::myZZ [private] |
Definition at line 228 of file ZoltanPartitioner.hpp.
Referenced by balance_mesh(), partition_inferred_mesh(), partition_mesh_and_geometry(), partition_owned_cells(), repartition(), SetHSFC_Parameters(), SetHypergraph_Parameters(), SetOCTPART_Parameters(), SetPARMETIS_Parameters(), SetRCB_Parameters(), SetRIB_Parameters(), and ~ZoltanPartitioner().
Range ZoltanPartitioner::partSets [private] |
Reimplemented from PartitionerBase< int >.
Definition at line 230 of file ZoltanPartitioner.hpp.
Referenced by include_closure(), and write_partition().