40 #include "CGMConfig.h"
42 #include "RefEntity.hpp"
43 #include "RefFace.hpp"
44 #include "RefEdge.hpp"
45 #include "RefVertex.hpp"
47 #include "TopologyEntity.hpp"
49 #include "CABodies.hpp"
50 #include "TDParallel.hpp"
51 #include "TDUniqueId.hpp"
57 if( MB_SUCCESS != result ) return result
75 const bool use_coords,
80 GeometryQueryTool* gqt
91 myZZ( NULL ), myNumPts( 0 ), argcArg( argc ), argvArg( argv )
105 const char* other_method,
106 const bool write_as_sets,
107 const bool write_as_tags )
109 if( !strcmp( zmethod,
"RR" ) && !strcmp( zmethod,
"RCB" ) && !strcmp( zmethod,
"RIB" ) &&
110 !strcmp( zmethod,
"HSFC" ) && !strcmp( zmethod,
"Hypergraph" ) && !strcmp( zmethod,
"PHG" ) &&
111 !strcmp( zmethod,
"PARMETIS" ) && !strcmp( zmethod,
"OCTPART" ) )
113 std::cout <<
"ERROR node " << mbpc->proc_config().proc_rank() <<
": Method must be "
114 <<
"RR, RCB, RIB, HSFC, Hypergraph (PHG), PARMETIS, or OCTPART" << std::endl;
118 std::vector< double > pts;
119 std::vector< int > ids;
120 std::vector< int > adjs,
length;
127 if( mbpc->proc_config().proc_rank() == 0 )
143 if( NULL ==
myZZ )
myZZ =
new Zoltan( mbpc->comm() );
145 if( NULL == zmethod || !strcmp( zmethod,
"RCB" ) )
147 else if( !strcmp( zmethod,
"RIB" ) )
149 else if( !strcmp( zmethod,
"HSFC" ) )
151 else if( !strcmp( zmethod,
"Hypergraph" ) || !strcmp( zmethod,
"PHG" ) )
152 if( NULL == other_method )
156 else if( !strcmp( zmethod,
"PARMETIS" ) )
158 if( NULL == other_method )
163 else if( !strcmp( zmethod,
"OCTPART" ) )
165 if( NULL == other_method )
186 ZOLTAN_ID_PTR importGlobalIds;
187 ZOLTAN_ID_PTR importLocalIds;
191 ZOLTAN_ID_PTR exportGlobalIds;
192 ZOLTAN_ID_PTR exportLocalIds;
196 int rc =
myZZ->LB_Partition( changes, numGidEntries, numLidEntries, numImport, importGlobalIds, importLocalIds,
197 importProcs, importToPart, numExport, exportGlobalIds, exportLocalIds, exportProcs,
215 mbFinalizePoints( (
int)ids.size(), numExport, exportLocalIds, exportProcs, &assignment );
217 if( mbpc->proc_config().proc_rank() == 0 )
219 result =
write_partition( mbpc->proc_config().proc_size(), elems, assignment, write_as_sets, write_as_tags );
223 free( (
int*)assignment );
228 myZZ->LB_Free_Part( &importGlobalIds, &importLocalIds, &importProcs, &importToPart );
229 myZZ->LB_Free_Part( &exportGlobalIds, &exportLocalIds, &exportProcs, &exportToPart );
244 std::vector< double >& y,
245 std::vector< double >& z,
251 int nprocs = mbpc->proc_config().proc_size();
252 int rank = mbpc->proc_config().proc_rank();
255 std::vector< double > pts;
256 pts.resize( x.size() * 3 );
257 std::vector< int > ids;
258 ids.resize( x.size() );
259 for(
size_t i = 0; i < x.size(); i++ )
262 pts[3 * i + 1] = y[i];
263 pts[3 * i + 2] = z[i];
264 ids[i] = StartID + (int)i;
279 if( rank == 0 ) std::cout <<
"Initializing zoltan..." << std::endl;
284 if( NULL ==
myZZ )
myZZ =
new Zoltan( mbpc->comm() );
286 if( NULL == zmethod || !strcmp( zmethod,
"RCB" ) )
288 else if( !strcmp( zmethod,
"RIB" ) )
290 else if( !strcmp( zmethod,
"HSFC" ) )
295 sprintf( buff,
"%d", nprocs );
296 int retval =
myZZ->Set_Param(
"NUM_GLOBAL_PARTITIONS", buff );
297 if( ZOLTAN_OK != retval )
return MB_FAILURE;
300 retval =
myZZ->Set_Param(
"RETURN_LISTS",
"ALL" );
301 if( ZOLTAN_OK != retval )
return MB_FAILURE;
316 ZOLTAN_ID_PTR import_global_ids, import_local_ids;
320 ZOLTAN_ID_PTR export_global_ids, export_local_ids;
321 int *assign_procs, *assign_parts;
324 std::cout <<
"Computing partition using " << ( zmethod ? zmethod :
"RCB" ) <<
" method for " << nprocs
325 <<
" processors..." << std::endl;
327 retval =
myZZ->LB_Partition( changes, numGidEntries, numLidEntries, num_import, import_global_ids, import_local_ids,
328 import_procs, import_to_part, num_export, export_global_ids, export_local_ids,
329 assign_procs, assign_parts );
330 if( ZOLTAN_OK != retval )
return MB_FAILURE;
334 std::cout <<
" time to LB_partition " << ( clock() -
t ) / (
double)CLOCKS_PER_SEC <<
"s. \n";
338 std::sort( import_global_ids, import_global_ids + num_import, std::greater< int >() );
339 std::sort( export_global_ids, export_global_ids + num_export, std::greater< int >() );
342 Range imported, exported;
343 std::copy( import_global_ids, import_global_ids + num_import,
range_inserter( imported ) );
344 std::copy( export_global_ids, export_global_ids + num_export,
range_inserter( exported ) );
345 localGIDs =
subtract( iniGids, exported );
346 localGIDs =
unite( localGIDs, imported );
348 retval =
myZZ->LB_Free_Part( &import_global_ids, &import_local_ids, &import_procs, &import_to_part );
349 if( ZOLTAN_OK != retval )
return MB_FAILURE;
350 retval =
myZZ->LB_Free_Part( &export_global_ids, &export_local_ids, &assign_procs, &assign_parts );
351 if( ZOLTAN_OK != retval )
return MB_FAILURE;
359 const bool write_as_sets,
360 int projection_type )
367 std::vector< double > elcoords( elverts.
size() * 3 );
370 std::vector< std::vector< EntityHandle > > part_assignments( num_parts );
374 for(
size_t iel = 0; iel < elverts.
size(); iel++ )
377 double* ecoords = &elcoords[iel * 3];
380 if( projection_type > 0 ) IntxUtils::transform_coordinates( ecoords, projection_type );
383 myZZ->LB_Point_PP_Assign( ecoords, proc, part );
386 part_assignments[part].push_back( elverts[iel] );
390 Tag part_set_tag = mbpc->partition_tag();
397 Interface::UNION );
RR;
401 size_t nparts_assigned = 0;
402 for(
size_t partnum = 0; partnum < num_parts; ++partnum )
404 std::vector< EntityHandle >& partvec = part_assignments[partnum];
406 nparts_assigned += ( partvec.size() ? 1 : 0 );
419 int ipartnum = (int)partnum;
428 std::vector< int > assignment( partvec.size(),
434 if( nparts_assigned != num_parts )
436 std::cout <<
"WARNING: The inference yielded lesser number of parts (" << nparts_assigned
437 <<
") than requested by user (" << num_parts <<
").\n";
446 const char* other_method,
449 const bool write_as_sets,
450 const bool write_as_tags,
451 const int obj_weight,
452 const int edge_weight,
454 const bool part_surf,
460 const int projection_type,
461 const bool recompute_rcb_box,
465 if( mbpc->proc_config().proc_size() != 1 )
467 std::cout <<
"ZoltanPartitioner::partition_mesh_and_geometry must be called in serial." << std::endl;
471 if( NULL != zmethod && strcmp( zmethod,
"RR" ) && strcmp( zmethod,
"RCB" ) && strcmp( zmethod,
"RIB" ) &&
472 strcmp( zmethod,
"HSFC" ) && strcmp( zmethod,
"Hypergraph" ) && strcmp( zmethod,
"PHG" ) &&
473 strcmp( zmethod,
"PARMETIS" ) && strcmp( zmethod,
"OCTPART" ) )
475 std::cout <<
"ERROR node " << mbpc->proc_config().proc_rank() <<
": Method must be "
476 <<
"RCB, RIB, HSFC, Hypergraph (PHG), PARMETIS, or OCTPART" << std::endl;
480 bool part_geom =
false;
481 if( 0 == strcmp( zmethod,
"RR" ) || 0 == strcmp( zmethod,
"RCB" ) || 0 == strcmp( zmethod,
"RIB" ) ||
482 0 == strcmp( zmethod,
"HSFC" ) )
484 std::vector< double > pts;
485 std::vector< int > ids;
486 std::vector< int > adjs,
length, parts;
487 std::vector< double > obj_weights, edge_weights;
498 if( !strcmp( zmethod,
"RR" ) )
500 if( part_geom_mesh_size < 0. )
504 if( elems.
empty() )
return MB_FAILURE;
506 std::vector< int > assign_vec( elems.
size() );
509 if( extra ) num_per++;
511 for(
int i = 0; i <
nparts; i++ )
513 if( i == extra ) num_per--;
514 std::fill( &assign_vec[nstart], &assign_vec[nstart + num_per], i );
523 result = partition_round_robin(
nparts );
RR;
530 std::cout <<
"Assembling graph..." << std::endl;
532 if( part_geom_mesh_size < 0. )
545 int n_ids = ids.size();
548 for(
int i = 0; i < n_ids; i++ )
550 std::cout <<
"graph_input_ids[" << i <<
"]=" << ids[i] <<
",obj_weights=" << obj_weights[i]
551 <<
",entity_id=" <<
entities.get_and_step()->id() <<
",part=" << parts[i] << std::endl;
552 for(
int j = 0; j <
length[i]; j++ )
554 std::cout <<
"adjs[" << j <<
"]=" << adjs[i_leng] <<
",edge_weights=" << edge_weights[i_leng]
564 std::cout <<
" time to assemble graph: " << ( clock() -
t ) / (
double)CLOCKS_PER_SEC <<
"s. \n";
567 double* o_wgt = NULL;
568 double* e_wgt = NULL;
569 if( obj_weights.size() > 0 ) o_wgt = &obj_weights[0];
570 if( edge_weights.size() > 0 ) e_wgt = &edge_weights[0];
581 std::cout <<
" time to initialize points: " << ( clock() -
t ) / (
double)CLOCKS_PER_SEC <<
"s. \n";
586 std::cout <<
"Initializing zoltan..." << std::endl;
591 if( NULL ==
myZZ )
myZZ =
new Zoltan( mbpc->comm() );
593 if( NULL == zmethod || !strcmp( zmethod,
"RCB" ) )
595 else if( !strcmp( zmethod,
"RIB" ) )
597 else if( !strcmp( zmethod,
"HSFC" ) )
599 else if( !strcmp( zmethod,
"Hypergraph" ) || !strcmp( zmethod,
"PHG" ) )
601 if( NULL == other_method || ( other_method[0] ==
'\0' ) )
608 std::ostringstream str;
610 myZZ->Set_Param(
"IMBALANCE_TOL", str.str().c_str() );
613 else if( !strcmp( zmethod,
"PARMETIS" ) )
615 if( NULL == other_method )
620 else if( !strcmp( zmethod,
"OCTPART" ) )
622 if( NULL == other_method )
630 sprintf( buff,
"%d",
nparts );
631 int retval =
myZZ->Set_Param(
"NUM_GLOBAL_PARTITIONS", buff );
632 if( ZOLTAN_OK != retval )
return MB_FAILURE;
635 retval =
myZZ->Set_Param(
"RETURN_LISTS",
"PARTITION ASSIGNMENTS" );
636 if( ZOLTAN_OK != retval )
return MB_FAILURE;
640 std::ostringstream str;
642 retval =
myZZ->Set_Param(
"OBJ_WEIGHT_DIM", str.str().c_str() );
643 if( ZOLTAN_OK != retval )
return MB_FAILURE;
646 if( edge_weight > 0 )
648 std::ostringstream str;
650 retval =
myZZ->Set_Param(
"EDGE_WEIGHT_DIM", str.str().c_str() );
651 if( ZOLTAN_OK != retval )
return MB_FAILURE;
662 if( part_geom_mesh_size > 0. )
673 ZOLTAN_ID_PTR dum_local, dum_global;
676 ZOLTAN_ID_PTR assign_gid, assign_lid;
677 int *assign_procs, *assign_parts;
679 std::cout <<
"Computing partition using " << ( zmethod ? zmethod :
"RCB" ) <<
" method for " <<
nparts
680 <<
" processors..." << std::endl;
683 if (NULL == zmethod || !strcmp(zmethod,
"RCB"))
684 Zoltan_Generate_Files(
myZZ->Get_C_Handle(), (
char*)zmethod, 1, 1, 0, 0);
686 if ( !strcmp(zmethod,
"PHG"))
687 Zoltan_Generate_Files(
myZZ->Get_C_Handle(), (
char*)zmethod, 1, 0, 1, 1);
690 retval =
myZZ->LB_Partition( changes, numGidEntries, numLidEntries, dumnum1, dum_global, dum_local, dum1, dum2,
691 num_assign, assign_gid, assign_lid, assign_procs, assign_parts );
692 if( ZOLTAN_OK != retval )
return MB_FAILURE;
696 std::cout <<
" time to LB_partition " << ( clock() -
t ) / (
double)CLOCKS_PER_SEC <<
"s. \n";
700 std::cout <<
"Saving partition information to MOAB..." << std::endl;
702 if( part_geom_mesh_size < 0. )
716 std::cout <<
" time to write partition in memory " << ( clock() -
t ) / (
double)CLOCKS_PER_SEC <<
"s. \n";
723 myZZ->LB_Free_Part( &assign_gid, &assign_lid, &assign_procs, &assign_parts );
733 std::cout <<
"Adding closure..." << std::endl;
741 if( ents.
empty() )
continue;
760 Range sets, part_ents;
777 if( !int_range.
empty() )
797 std::vector< double >& coords,
798 std::vector< int >& moab_ids,
799 std::vector< int >& adjacencies,
800 std::vector< int >&
length,
803 int projection_type )
816 result = mbpc->assign_global_ids( rootset, dimension, 1,
true,
true );
RR;
826 double avg_position[3];
850 std::copy( neighbors, neighbors + adjs.
size(), std::back_inserter( adjacencies ) );
860 moab_ids.push_back( moab_id );
862 if( projection_type > 0 ) IntxUtils::transform_coordinates( avg_position, projection_type );
864 std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
869 std::cout <<
"Length vector: " << std::endl;
870 std::copy(
length.begin(),
length.end(), std::ostream_iterator< int >( std::cout,
", " ) );
871 std::cout << std::endl;
872 std::cout <<
"Adjacencies vector: " << std::endl;
873 std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< int >( std::cout,
", " ) );
874 std::cout << std::endl;
875 std::cout <<
"Moab_ids vector: " << std::endl;
876 std::copy( moab_ids.begin(), moab_ids.end(), std::ostream_iterator< int >( std::cout,
", " ) );
877 std::cout << std::endl;
878 std::cout <<
"Coords vector: " << std::endl;
879 std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( std::cout,
", " ) );
880 std::cout << std::endl;
888 std::vector< double >& ,
889 std::vector< int >& moab_ids,
890 std::vector< int >& adjacencies,
891 std::vector< int >&
length,
892 std::vector< double >& obj_weights,
893 std::vector< double >& edge_weights,
894 std::vector< int >& parts,
896 const double part_geom_mesh_size,
900 DLIList< RefEntity* > body_list;
901 gti->ref_entity_list(
"body", body_list, CUBIT_FALSE );
902 DLIList< RefFace* > all_shared_surfs;
903 int n_bodies = body_list.size();
904 int body_map_index = 1;
905 int surf_map_index = n_bodies + 1;
906 int n_bodies_proc = n_bodies / n_part;
907 int i_bodies_proc = n_bodies_proc;
911 for(
int i = 0; i < n_bodies; i++ )
914 if( i == i_bodies_proc )
918 i_bodies_proc += n_bodies_proc;
925 parts.push_back( proc );
928 RefEntity* body = body_list.get_and_step();
929 double vertex_w = body->measure();
930 vertex_w /= part_geom_mesh_size * part_geom_mesh_size * part_geom_mesh_size;
931 vertex_w = 3.8559e-5 * vertex_w * log( vertex_w );
934 DLIList< RefFace* > shared_surfs;
935 DLIList< RefFace* > faces;
936 (
dynamic_cast< TopologyEntity*
>( body ) )->ref_faces( faces );
937 int n_face = faces.size();
939 for(
int j = 0; j < n_face; j++ )
941 RefFace*
face = faces.get_and_step();
942 TopologyEntity* te = CAST_TO(
face, TopologyEntity );
943 if( te->bridge_manager()->number_of_bridges() > 1 )
945 shared_surfs.append(
face );
949 vertex_w += estimate_face_mesh_load(
face,
face->measure() );
953 int temp_index = body_map_index++;
954 body_vertex_map[body->id()] = temp_index;
955 moab_ids.push_back( temp_index );
956 obj_weights.push_back( vertex_w );
960 std::cout <<
"body=" << body->id() <<
",graph_id=" << temp_index <<
",weight=" << vertex_w
961 <<
",part=" << proc << std::endl;
965 int n_shared = shared_surfs.size();
966 shared_surfs.reset();
967 for(
int k = 0; k < n_shared; k++ )
969 RefFace*
face = shared_surfs.get_and_step();
970 std::map< int, int >::iterator iter = surf_vertex_map.find(
face->id() );
971 if( iter != surf_vertex_map.end() )
973 temp_index = ( *iter ).second;
977 temp_index = surf_map_index++;
978 surf_vertex_map[
face->id()] = temp_index;
979 all_shared_surfs.append(
face );
981 adjacencies.push_back( temp_index );
982 double tmp_sw = estimate_face_comm_load(
face, part_geom_mesh_size );
983 edge_weights.push_back( tmp_sw );
987 std::cout <<
"adjac=" << temp_index <<
",weight=" << tmp_sw << std::endl;
990 length.push_back( n_shared );
995 int n_all_shared_surf = all_shared_surfs.size();
996 all_shared_surfs.reset();
997 for(
int i = 0; i < n_all_shared_surf; i++ )
999 RefEntity*
face = all_shared_surfs.get_and_step();
1000 moab_ids.push_back( surf_vertex_map[
face->id()] );
1001 double face_mesh_load = estimate_face_mesh_load(
face, part_geom_mesh_size );
1002 obj_weights.push_back( face_mesh_load );
1006 double min_load = std::numeric_limits< double >::max();
1008 DLIList< Body* > parents;
1009 dynamic_cast< TopologyEntity*
>(
face )->bodies( parents );
1010 int n_parents = parents.size();
1012 for(
int j = 0; j < n_parents; j++ )
1014 int body_gid = body_vertex_map[parents.get_and_step()->id()];
1015 adjacencies.push_back( body_gid );
1016 edge_weights.push_back( estimate_face_comm_load(
face, part_geom_mesh_size ) );
1018 if( obj_weights[body_gid - 1] < min_load )
1020 min_ind = body_gid - 1;
1021 min_load = obj_weights[min_ind];
1024 length.push_back( n_parents );
1026 obj_weights[min_ind] += face_mesh_load;
1027 parts.push_back( parts[min_ind] );
1031 std::cout <<
"shared_surf=" <<
face->id() <<
",graph_id=" << surf_vertex_map[
face->id()]
1032 <<
",weight=" << face_mesh_load <<
",part=" << parts[min_ind] << std::endl;
1036 for(
size_t i = 0; i < obj_weights.size(); i++ )
1037 if( obj_weights[i] < 1. ) obj_weights[i] = 1.;
1038 for(
size_t i = 0; i < edge_weights.size(); i++ )
1039 if( edge_weights[i] < 1. ) edge_weights[i] = 1.;
1044 double ZoltanPartitioner::estimate_face_mesh_load( RefEntity*
face,
const double h )
1046 GeometryType type = CAST_TO(
face, RefFace )->geometry_type();
1047 double n =
face->measure() / h / h;
1048 double n_logn = n * log( n );
1050 if( type == PLANE_SURFACE_TYPE )
1052 return 1.536168737505151e-4 * n_logn;
1054 else if( type == SPLINE_SURFACE_TYPE )
1056 return 5.910511018383144e-4 * n_logn;
1058 else if( type == CONE_SURFACE_TYPE || type == SPHERE_SURFACE_TYPE || type == TORUS_SURFACE_TYPE )
1060 return 2.352511671418708e-4 * n_logn;
1066 double ZoltanPartitioner::estimate_face_comm_load( RefEntity*
face,
const double h )
1069 #if( ( CGM_MAJOR_VERSION == 14 && CGM_MINOR_VERSION > 2 ) || CGM_MAJOR_VERSION >= 15 )
1070 DLIList< DLIList< RefEdge* > > ref_edge_loops;
1072 DLIList< DLIList< RefEdge* >* > ref_edge_loops;
1074 CAST_TO(
face, RefFace )->ref_edge_loops( ref_edge_loops );
1075 ref_edge_loops.reset();
1077 #if( ( CGM_MAJOR_VERSION == 14 && CGM_MINOR_VERSION > 2 ) || CGM_MAJOR_VERSION >= 15 )
1078 for(
int i = 0; i < ref_edge_loops.size(); i++ )
1080 DLIList< RefEdge* > eloop = ref_edge_loops.get_and_step();
1082 for(
int j = 0; j < eloop.size(); j++ )
1084 peri += eloop.get_and_step()->measure();
1088 for(
int i = 0; i < ref_edge_loops.size(); i++ )
1090 DLIList< RefEdge* >* eloop = ref_edge_loops.get_and_step();
1092 for(
int j = 0; j < eloop->size(); j++ )
1094 peri += eloop->get_and_step()->measure();
1100 return ( 104 *
face->measure() / sqrt( 3 ) / h / h + 56 / 3 * peri / h ) / 700000.;
1105 const int* assignment,
1106 std::vector< double >& obj_weights,
1107 const bool part_surf,
1113 CGMApp::instance()->attrib_manager()->register_attrib_type( CA_BODIES,
"bodies",
"BODIES", CABodies_creator,
1114 CUBIT_TRUE, CUBIT_TRUE, CUBIT_TRUE, CUBIT_TRUE,
1115 CUBIT_TRUE, CUBIT_FALSE );
1116 CGMApp::instance()->attrib_manager()->auto_flag( CUBIT_TRUE );
1121 for(
int i = 0; i < n_entities; i++ )
1123 int proc = assignment[i];
1124 DLIList< int > shared_procs;
1125 RefEntity* entity =
entities.get_and_step();
1127 if( entity->entity_type_info() ==
typeid( Body ) )
1129 shared_procs.append( proc );
1130 TDParallel* td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1131 if( td_par == NULL ) td_par =
new TDParallel( entity, NULL, &shared_procs );
1135 std::cout <<
"body" << entity->id() <<
"_is_partitioned_to_p" << proc << std::endl;
1139 DLIList< RefVolume* > volumes;
1140 (
dynamic_cast< TopologyEntity*
>( entity ) )->ref_volumes( volumes );
1141 int n_vol = volumes.size();
1143 for(
int j = 0; j < n_vol; j++ )
1145 RefEntity* vol = volumes.get_and_step();
1146 td_par = (TDParallel*)vol->get_TD( &TDParallel::is_parallel );
1147 if( td_par == NULL ) td_par =
new TDParallel( vol, NULL, &shared_procs );
1154 for(
int i = 0; i < n_entities; i++ )
1156 int proc = assignment[i];
1157 DLIList< int > shared_procs;
1158 RefEntity* entity =
entities.get_and_step();
1160 if( entity->entity_type_info() ==
typeid( RefFace ) )
1162 DLIList< Body* > parents;
1163 (
dynamic_cast< TopologyEntity*
>( entity ) )->bodies( parents );
1164 int n_parents = parents.size();
1165 if( n_parents != 2 )
1167 std::cerr <<
"# of parent bodies of interface surface should be 2." << std::endl;
1170 shared_procs.append( proc );
1172 for(
int j = 0; j < 2; j++ )
1174 RefEntity* parent = parents.get_and_step();
1175 TDParallel* parent_td = (TDParallel*)parent->get_TD( &TDParallel::is_parallel );
1177 if( parent_td == NULL )
1179 std::cerr <<
"parent body should have balanced process." << std::endl;
1182 int temp_proc = parent_td->get_charge_proc();
1183 if( temp_proc != proc ) shared_procs.append( temp_proc );
1186 if( shared_procs.size() > 1 )
1188 int merge_id = TDUniqueId::get_unique_id( entity );
1189 TDParallel* td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1190 if( td_par == NULL ) td_par =
new TDParallel( entity, NULL, &shared_procs, NULL, merge_id, 1 );
1194 std::cout <<
"surf" << entity->id() <<
"_is_partitioned_to_p";
1195 for(
int j = 0; j < shared_procs.size(); j++ )
1197 std::cout <<
"," << shared_procs[j];
1199 std::cout << std::endl;
1208 result = partition_surface(
nparts,
entities, assignment, obj_weights );
RR;
1212 result = partition_child_entities( 1,
nparts, part_surf, ghost );
RR;
1213 result = partition_child_entities( 0,
nparts, part_surf );
RR;
1218 for(
int i = 0; i < n_entities; i++ )
1220 RefEntity* entity =
entities.get_and_step();
1221 if( entity->entity_type_info() ==
typeid( Body ) )
1223 TDParallel* td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1224 CubitString st = entity->entity_name();
1225 DLIList< int >* sp = td_par->get_shared_proc_list();
1226 int n_sp = sp->size();
1228 for(
int j = 0; j < n_sp; j++ )
1230 std::cout <<
"partitioned_" << st.c_str() <<
",proc=" << sp->get_and_step() << std::endl;
1232 DLIList< int >* gp = td_par->get_ghost_proc_list();
1233 int n_gp = gp->size();
1235 for(
int j = 0; j < n_gp; j++ )
1237 std::cout <<
"partitioned_" << st.c_str() <<
",ghost=" << gp->get_and_step() << std::endl;
1248 const int* assignment,
1249 std::vector< double >& obj_weights )
1252 double ave_load = 0.;
1253 double* loads =
new double[
nparts];
1254 for( i = 0; i <
nparts; i++ )
1259 for( i = 0; i < n_entities; i++ )
1261 loads[assignment[i]] += obj_weights[i];
1262 ave_load += obj_weights[i];
1268 for( i = 0; i <
nparts; i++ )
1270 std::cout <<
"loads_before_surface_partition[" << i <<
"]=" << loads[i] << std::endl;
1275 bool b_stop =
false;
1279 int max_proc =
nparts, min_proc = 0;
1280 double min_load = std::numeric_limits< double >::max();
1281 double max_load = std::numeric_limits< double >::min();
1282 for( i = 0; i <
nparts; i++ )
1284 if( loads[i] < min_load )
1286 min_load = loads[i];
1289 if( loads[i] > max_load )
1291 max_load = loads[i];
1296 double load_diff = max_load - ave_load;
1297 if( load_diff > ave_load / 10. )
1299 bool b_moved =
false;
1301 for( i = 0; i < n_entities; i++ )
1303 if( b_moved )
break;
1304 if( assignment[i] == max_proc &&
1305 entities[i]->entity_type_info() ==
typeid( Body ) )
1307 DLIList< RefFace* > faces;
1308 (
dynamic_cast< TopologyEntity*
>(
entities[i] ) )->ref_faces( faces );
1309 int n_face = faces.size();
1311 for(
int j = 0; j < n_face; j++ )
1313 RefFace*
face = faces.get_and_step();
1314 TopologyEntity* te = CAST_TO(
face, TopologyEntity );
1315 if( te->bridge_manager()->number_of_bridges() < 2 )
1317 TDParallel* td_par = (TDParallel*)
face->get_TD( &TDParallel::is_parallel );
1318 if( td_par == NULL )
1320 double face_load =
face->measure();
1321 if( load_diff > min_load + face_load - ave_load )
1323 loads[max_proc] -= face_load;
1324 loads[min_proc] += face_load;
1325 int merge_id = TDUniqueId::get_unique_id(
face );
1326 DLIList< int > shared_procs;
1327 shared_procs.append( min_proc );
1328 shared_procs.append( max_proc );
1329 td_par =
new TDParallel(
face, NULL, &shared_procs, NULL, merge_id, 1 );
1333 std::cout <<
"non-shared surface " <<
face->id() <<
" is moved from p"
1334 << max_proc <<
" to p" << min_proc << std::endl;
1349 }
while( !b_stop && n_iter < 50 );
1353 for( i = 0; i <
nparts; i++ )
1355 std::cout <<
"loads_after_surface_partition[" << i <<
"]=" << loads[i] << std::endl;
1363 ErrorCode ZoltanPartitioner::partition_round_robin(
const int n_part )
1366 double* loads =
new double[n_part];
1367 double* ve_loads =
new double[n_part];
1368 for( i = 0; i < n_part; i++ )
1373 DLIList< RefEntity* > body_entity_list;
1374 gti->ref_entity_list(
"body", body_entity_list, CUBIT_FALSE );
1375 int n_entity = body_entity_list.size();
1376 int n_entity_proc = n_entity / n_part;
1377 int i_entity_proc = n_entity_proc;
1382 body_entity_list.reset();
1383 for( i = 0; i < n_entity; i++ )
1385 if( i == i_entity_proc )
1389 i_entity_proc += n_entity_proc;
1398 entity = body_entity_list.get_and_step();
1399 DLIList< int > shared_procs;
1400 shared_procs.append( proc );
1401 TDParallel* td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1402 if( td_par == NULL ) td_par =
new TDParallel( entity, NULL, &shared_procs );
1403 loads[proc] += entity->measure();
1406 DLIList< RefVolume* > volumes;
1407 (
dynamic_cast< TopologyEntity*
>( entity ) )->ref_volumes( volumes );
1408 int n_vol = volumes.size();
1410 for( j = 0; j < n_vol; j++ )
1412 RefEntity* vol = volumes.get_and_step();
1413 td_par = (TDParallel*)vol->get_TD( &TDParallel::is_parallel );
1414 if( td_par == NULL ) td_par =
new TDParallel( vol, NULL, &shared_procs );
1418 DLIList< RefFace* > faces;
1419 (
dynamic_cast< TopologyEntity*
>( entity ) )->ref_faces( faces );
1420 int n_face = faces.size();
1422 for( j = 0; j < n_face; j++ )
1424 RefFace*
face = faces.get_and_step();
1425 TopologyEntity* te = CAST_TO(
face, TopologyEntity );
1426 if( te->bridge_manager()->number_of_bridges() < 2 ) loads[proc] = loads[proc] +
face->measure();
1430 DLIList< RefEntity* > child_list;
1431 RefEntity::get_all_child_ref_entities( body_entity_list, child_list );
1432 int n_child = child_list.size();
1436 for( j = 0; j < n_child; j++ )
1438 entity = child_list.get_and_step();
1439 TopologyEntity* te = CAST_TO( entity, TopologyEntity );
1441 if( te->bridge_manager()->number_of_bridges() > 1 )
1443 DLIList< Body* > parent_bodies;
1444 DLIList< int > child_shared_procs;
1445 (
dynamic_cast< TopologyEntity*
>( entity ) )->bodies( parent_bodies );
1446 int n_parent = parent_bodies.size();
1448 for( k = 0; k < n_parent; k++ )
1450 RefEntity* parent_vol = CAST_TO( parent_bodies.get_and_step(), RefEntity );
1451 TDParallel* parent_td = (TDParallel*)parent_vol->get_TD( &TDParallel::is_parallel );
1453 if( parent_td == NULL )
1455 PRINT_ERROR(
"parent Volume has to be partitioned." );
1460 child_shared_procs.append_unique( parent_td->get_charge_proc() );
1463 if( child_shared_procs.size() > 1 )
1465 td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1466 if( td_par == NULL )
1468 int merge_id = TDUniqueId::get_unique_id( entity );
1469 if( entity->entity_type_info() ==
typeid( RefFace ) )
1471 if( child_shared_procs.size() != 2 )
1473 PRINT_ERROR(
"Error: # of shared processors of interface surface "
1481 if( loads[child_shared_procs[0]] > loads[child_shared_procs[1]] )
1482 child_shared_procs.reverse();
1484 loads[child_shared_procs[0]] = loads[child_shared_procs[0]] + entity->measure();
1485 td_par =
new TDParallel( entity, NULL, &child_shared_procs, NULL, merge_id, 1 );
1487 else if( entity->entity_type_info() ==
typeid( RefEdge ) ||
1488 entity->entity_type_info() ==
typeid( RefVertex ) )
1491 int min_p = child_shared_procs[0];
1492 int n_shared_proc = child_shared_procs.size();
1493 for( k = 1; k < n_shared_proc; k++ )
1495 if( ve_loads[child_shared_procs[k]] < ve_loads[min_p] ) min_p = child_shared_procs[k];
1497 ve_loads[min_p] = ve_loads[min_p] + entity->measure();
1498 child_shared_procs.remove( min_p );
1499 child_shared_procs.insert_first( min_p );
1500 td_par =
new TDParallel( entity, NULL, &child_shared_procs, NULL, merge_id, 1 );
1515 ErrorCode ZoltanPartitioner::partition_child_entities(
const int dim,
1517 const bool part_surf,
1520 DLIList< RefEntity* > entity_list;
1522 gti->ref_entity_list(
"vertex", entity_list, CUBIT_FALSE );
1524 gti->ref_entity_list(
"curve", entity_list, CUBIT_FALSE );
1527 std::cerr <<
"Dimention should be from 0 to 1." << std::endl;
1532 int n_entity = entity_list.size();
1533 double* loads =
new double[n_part];
1534 for( i = 0; i < n_part; i++ )
1536 entity_list.reset();
1538 for( i = 0; i < n_entity; i++ )
1540 RefEntity* entity = entity_list.get_and_step();
1541 TopologyEntity* te = CAST_TO( entity, TopologyEntity );
1543 if( !part_surf && te->bridge_manager()->number_of_bridges() < 2 )
continue;
1545 DLIList< int > shared_procs;
1546 DLIList< Body* > parents;
1547 (
dynamic_cast< TopologyEntity*
>( entity ) )->bodies( parents );
1548 int n_parents = parents.size();
1549 std::set< int > s_proc;
1553 for( j = 0; j < n_parents; j++ )
1555 RefEntity* parent = parents.get_and_step();
1556 TDParallel* parent_td = (TDParallel*)parent->get_TD( &TDParallel::is_parallel );
1558 if( parent_td != NULL )
1560 DLIList< int >* parent_procs = parent_td->get_shared_proc_list();
1561 int n_shared = parent_procs->size();
1562 parent_procs->reset();
1563 for( k = 0; k < n_shared; k++ )
1565 int p = parent_procs->get_and_step();
1573 DLIList< RefFace* > parent_faces;
1574 (
dynamic_cast< TopologyEntity*
>( entity ) )->ref_faces( parent_faces );
1575 int n_pface = parent_faces.size();
1576 parent_faces.reset();
1579 for( j = 0; j < n_pface; j++ )
1581 RefEntity* parent = parent_faces.get_and_step();
1582 TDParallel* parent_td = (TDParallel*)parent->get_TD( &TDParallel::is_parallel );
1584 if( parent_td != NULL )
1586 DLIList< int >* parent_procs = parent_td->get_shared_proc_list();
1587 int n_shared = parent_procs->size();
1588 parent_procs->reset();
1590 for( k = 0; k < n_shared; k++ )
1592 int p = parent_procs->get_and_step();
1601 if( s_proc.size() > 1 )
1604 double min_load = std::numeric_limits< double >::max();
1605 std::set< int >::iterator iter = s_proc.begin();
1606 std::set< int >::iterator end_iter = s_proc.end();
1607 for( ; iter != end_iter; ++iter )
1609 if( loads[*iter] < min_load )
1611 min_load = loads[*iter];
1617 loads[min_proc] += entity->measure();
1619 loads[min_proc] += 1.;
1620 shared_procs.append( min_proc );
1621 iter = s_proc.begin();
1622 end_iter = s_proc.end();
1623 for( ; iter != end_iter; ++iter )
1625 if( *iter != min_proc )
1627 shared_procs.append( *iter );
1635 for( j = 0; j < n_parents; j++ )
1637 RefEntity* parent_vol = CAST_TO( parents.get_and_step(), RefEntity );
1638 TDParallel* parent_td = (TDParallel*)parent_vol->get_TD( &TDParallel::is_parallel );
1639 int n_shared_proc = shared_procs.size();
1641 for( k = 0; k < n_shared_proc; k++ )
1643 parent_td->add_ghost_proc( shared_procs[k] );
1649 int merge_id = TDUniqueId::get_unique_id( entity );
1650 TDParallel* td_par = (TDParallel*)entity->get_TD( &TDParallel::is_parallel );
1651 if( td_par == NULL ) td_par =
new TDParallel( entity, NULL, &shared_procs, NULL, merge_id, 1 );
1662 const int* assignment,
1663 const bool write_as_sets,
1664 const bool write_as_tags )
1678 if( !tagged_sets.
empty() )
1681 if( !write_as_sets )
1696 for( i = 0; i < num_new; i++ )
1700 tagged_sets.
insert( new_set );
1707 for( i = 0; i < num_del; i++ )
1718 int* dum_ids =
new int[
nparts];
1719 for( i = 0; i <
nparts; i++ )
1728 std::vector< EntityHandle > tmp_part_sets;
1739 for( i = 0, rit = elems.
begin(); rit != elems.
end(); ++rit, i++ )
1756 if( !empty_sets.
empty() )
1758 std::cout <<
"WARNING: " << empty_sets.
size() <<
" empty sets in partition: ";
1759 for( rit = empty_sets.
begin(); rit != empty_sets.
end(); ++rit )
1760 std::cout << *rit <<
" ";
1761 std::cout << std::endl;
1776 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nRecursive Coordinate Bisection" << std::endl;
1779 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1780 myZZ->Set_Param(
"LB_METHOD",
"RCB" );
1785 myZZ->Set_Param(
"RCB_OUTPUT_LEVEL",
"1" );
1786 myZZ->Set_Param(
"KEEP_CUTS",
"1" );
1788 if( recompute_rcb_box )
myZZ->Set_Param(
"RCB_RECOMPUTE_BOX",
"1" );
1793 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nRecursive Inertial Bisection" << std::endl;
1796 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1797 myZZ->Set_Param(
"LB_METHOD",
"RIB" );
1801 myZZ->Set_Param(
"KEEP_CUTS",
"1" );
1802 myZZ->Set_Param(
"AVERAGE_CUTS",
"1" );
1807 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nHilbert Space Filling Curve" << std::endl;
1810 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1811 myZZ->Set_Param(
"LB_METHOD",
"HSFC" );
1815 myZZ->Set_Param(
"KEEP_CUTS",
"1" );
1820 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nHypergraph (or PHG): " << std::endl;
1823 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1824 myZZ->Set_Param(
"LB_METHOD",
"Hypergraph" );
1827 myZZ->Set_Param(
"PHG_COARSEPARTITION_METHOD", phg_method );
1832 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nPARMETIS: " << parmetis_method << std::endl;
1835 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1836 myZZ->Set_Param(
"LB_METHOD",
"PARMETIS" );
1840 myZZ->Set_Param(
"PARMETIS_METHOD", parmetis_method );
1845 if( mbpc->proc_config().proc_rank() == 0 ) std::cout <<
"\nOctree Partitioning: " << oct_method << std::endl;
1848 myZZ->Set_Param(
"DEBUG_LEVEL",
"0" );
1849 myZZ->Set_Param(
"LB_METHOD",
"OCTPART" );
1853 myZZ->Set_Param(
"OCT_METHOD", oct_method );
1854 myZZ->Set_Param(
"OCT_OUTPUT_LEVEL",
"3" );
1862 double* obj_weights,
1863 double* edge_weights,
1869 int *numPts, *nborProcs = NULL;
1870 int sum, ptsPerProc, ptsAssigned, mySize;
1874 int* sendEdges = NULL;
1875 int* sendNborId = NULL;
1878 if( mbpc->proc_config().proc_rank() == 0 )
1882 numPts = (
int*)malloc(
sizeof(
int ) * mbpc->proc_config().proc_size() );
1883 ptsPerProc = npts / mbpc->proc_config().proc_size();
1886 for( i = 0; i < mbpc->proc_config().proc_size() - 1; i++ )
1888 numPts[i] = ptsPerProc;
1889 ptsAssigned += ptsPerProc;
1892 numPts[mbpc->proc_config().proc_size() - 1] = npts - ptsAssigned;
1894 mySize = numPts[mbpc->proc_config().proc_rank()];
1895 sendPts = pts + ( 3 * numPts[0] );
1896 sendIds = ids + numPts[0];
1900 sendEdges =
length + numPts[0];
1902 for( j = 0; j < numPts[0]; j++ )
1905 sendNborId = adjs +
sum;
1907 for( j = numPts[0]; j < npts; j++ )
1910 nborProcs = (
int*)malloc(
sizeof(
int ) *
sum );
1912 for( j = 0; j <
sum; j++ )
1913 if( ( i = adjs[j] / ptsPerProc ) < mbpc->proc_config().proc_size() )
1916 nborProcs[j] = mbpc->proc_config().proc_size() - 1;
1918 sendProcs = nborProcs + ( sendNborId - adjs );
1920 for( i = 1; i < mbpc->proc_config().proc_size(); i++ )
1922 MPI_Send( &numPts[i], 1, MPI_INT, i, 0x00, mbpc->comm() );
1923 MPI_Send( sendPts, 3 * numPts[i], MPI_DOUBLE, i, 0x01, mbpc->comm() );
1924 MPI_Send( sendIds, numPts[i], MPI_INT, i, 0x03, mbpc->comm() );
1925 MPI_Send( sendEdges, numPts[i], MPI_INT, i, 0x06, mbpc->comm() );
1928 for( j = 0; j < numPts[i]; j++ )
1929 sum += sendEdges[j];
1931 MPI_Send( sendNborId,
sum, MPI_INT, i, 0x07, mbpc->comm() );
1932 MPI_Send( sendProcs,
sum, MPI_INT, i, 0x08, mbpc->comm() );
1933 sendPts += ( 3 * numPts[i] );
1934 sendIds += numPts[i];
1935 sendEdges += numPts[i];
1944 MPI_Recv( &mySize, 1, MPI_INT, 0, 0x00, mbpc->comm(), &stat );
1945 pts = (
double*)malloc(
sizeof(
double ) * 3 * mySize );
1946 ids = (
int*)malloc(
sizeof(
int ) * mySize );
1947 length = (
int*)malloc(
sizeof(
int ) * mySize );
1948 if( obj_weights != NULL ) obj_weights = (
double*)malloc(
sizeof(
double ) * mySize );
1949 MPI_Recv( pts, 3 * mySize, MPI_DOUBLE, 0, 0x01, mbpc->comm(), &stat );
1950 MPI_Recv( ids, mySize, MPI_INT, 0, 0x03, mbpc->comm(), &stat );
1951 MPI_Recv(
length, mySize, MPI_INT, 0, 0x06, mbpc->comm(), &stat );
1954 for( j = 0; j < mySize; j++ )
1957 adjs = (
int*)malloc(
sizeof(
int ) *
sum );
1958 if( edge_weights != NULL ) edge_weights = (
double*)malloc(
sizeof(
double ) *
sum );
1959 nborProcs = (
int*)malloc(
sizeof(
int ) *
sum );
1960 MPI_Recv( adjs,
sum, MPI_INT, 0, 0x07, mbpc->comm(), &stat );
1961 MPI_Recv( nborProcs,
sum, MPI_INT, 0, 0x08, mbpc->comm(), &stat );
1979 ZOLTAN_ID_PTR exportLocalIDs,
1991 if( mbpc->proc_config().proc_rank() == 0 )
1992 MyAssignment = (
int*)malloc(
sizeof(
int ) * npts );
1994 MyAssignment = (
int*)malloc(
sizeof(
int ) *
NumPoints );
1997 MyAssignment[i] = mbpc->proc_config().proc_rank();
1999 for( i = 0; i < numExport; i++ )
2000 MyAssignment[exportLocalIDs[i]] = exportProcs[i];
2002 if( mbpc->proc_config().proc_rank() == 0 )
2007 for( i = 1; i < (int)mbpc->proc_config().proc_size(); i++ )
2009 MPI_Recv( &numPts, 1, MPI_INT, i, 0x04, mbpc->comm(), &stat );
2010 MPI_Recv( recvA, numPts, MPI_INT, i, 0x05, mbpc->comm(), &stat );
2014 *assignment = MyAssignment;
2018 MPI_Send( &
NumPoints, 1, MPI_INT, 0, 0x04, mbpc->comm() );
2019 MPI_Send( MyAssignment,
NumPoints, MPI_INT, 0, 0x05, mbpc->comm() );
2020 free( MyAssignment );
2028 int* vals = (
int*)malloc( mbpc->proc_config().proc_size() *
sizeof( int ) );
2030 MPI_Allgather( &rc, 1, MPI_INT, vals, 1, MPI_INT, mbpc->comm() );
2032 for( i = 0; i < mbpc->proc_config().proc_size(); i++ )
2034 if( vals[i] != ZOLTAN_OK )
2036 if( 0 == mbpc->proc_config().proc_rank() )
2051 int* v1 = (
int*)malloc( 4 *
sizeof(
int ) );
2060 if( mbpc->proc_config().proc_rank() == 0 )
2062 v2 = (
int*)malloc( 4 * mbpc->proc_config().proc_size() *
sizeof( int ) );
2065 MPI_Gather( v1, 4, MPI_INT, v2, 4, MPI_INT, 0, mbpc->comm() );
2067 if( mbpc->proc_config().proc_rank() == 0 )
2069 fprintf( stdout,
"======%s======\n", s );
2070 for( i = 0, v = v2; i < mbpc->proc_config().proc_size(); i++, v += 4 )
2072 fprintf( stdout,
"%u: originally had %d, import %d, exp %d, %s\n", i, v[0], v[1], v[2],
2073 v[3] ?
"a change of partitioning" :
"no change" );
2075 fprintf( stdout,
"==========================================\n" );
2086 if( s ) printf(
"%s ", s );
2091 printf(
"%d: SUCCESSFUL\n", mbpc->proc_config().proc_rank() );
2094 printf(
"%d: WARNING\n", mbpc->proc_config().proc_rank() );
2097 printf(
"%d: FATAL ERROR\n", mbpc->proc_config().proc_rank() );
2100 printf(
"%d: MEMORY ALLOCATION ERROR\n", mbpc->proc_config().proc_rank() );
2103 printf(
"%d: INVALID RETURN CODE\n", mbpc->proc_config().proc_rank() );
2131 if( wgt_dim > 0 ) obj_wgts[i] =
ObjWeights[i];
2162 for( i = 0; i < numObjs; i++ )
2174 pts[next++] =
Points[id3];
2175 pts[next++] =
Points[id3 + 1];
2176 pts[next++] =
Points[id3 + 2];
2192 for( i = 0; i < numObjs; i++ )
2213 ZOLTAN_ID_PTR nborGlobalIds,
2219 int i, id, idSum, j;
2222 for( i = 0; i < numObjs; i++ )
2234 for( j = 0; j < id; j++ )
2237 for( j = 0; j <
NumEdges[id]; j++ )
2241 if( wgt_dim > 0 ) edge_wgts[next] =
EdgeWeights[idSum];
2260 for( i = 0; i < numObjs; i++ )
2270 part[next++] =
Parts[id];
2276 std::multimap< int, int >& extraGraphEdges,
2277 std::map< int, int > procs,
2278 int& numNewPartitions,
2279 std::map< int, Range >& distribution,
2286 std::vector< int > adjacencies;
2287 std::vector< int > ids;
2288 ids.resize( primary.
size() );
2289 std::vector< int >
length;
2290 std::vector< double > coords;
2291 std::vector< int > nbor_proc;
2296 double avg_position[3];
2305 int rank = mbpc->rank();
2323 int size_adjs = (int)adjs.
size();
2325 for(
int k = 0; k < size_adjs; k++ )
2326 neib_proc[k] = rank;
2327 if( extraGraphEdges.find( moab_id ) != extraGraphEdges.end() )
2331 std::pair< std::multimap< int, int >::iterator, std::multimap< int, int >::iterator > ret;
2332 ret = extraGraphEdges.equal_range( moab_id );
2333 for( std::multimap< int, int >::iterator it = ret.first; it != ret.second; ++it )
2335 int otherID = it->second;
2336 neighbors[size_adjs] = otherID;
2337 neib_proc[size_adjs] = procs[otherID];
2343 length.push_back( size_adjs );
2344 std::copy( neighbors, neighbors + size_adjs, std::back_inserter( adjacencies ) );
2345 std::copy( neib_proc, neib_proc + size_adjs, std::back_inserter( nbor_proc ) );
2357 std::copy( avg_position, avg_position + 3, std::back_inserter( coords ) );
2362 std::stringstream ff2;
2363 ff2 <<
"zoltanInput_" << mbpc->rank() <<
".txt";
2365 ofs.open( ff2.str().c_str(), std::ofstream::out );
2366 ofs <<
"Length vector: " << std::endl;
2367 std::copy(
length.begin(),
length.end(), std::ostream_iterator< int >( ofs,
", " ) );
2369 ofs <<
"Adjacencies vector: " << std::endl;
2370 std::copy( adjacencies.begin(), adjacencies.end(), std::ostream_iterator< int >( ofs,
", " ) );
2372 ofs <<
"Moab_ids vector: " << std::endl;
2373 std::copy( ids.begin(), ids.end(), std::ostream_iterator< int >( ofs,
", " ) );
2375 ofs <<
"Coords vector: " << std::endl;
2376 std::copy( coords.begin(), coords.end(), std::ostream_iterator< double >( ofs,
", " ) );
2383 if( 1 != met )
Points = &coords[0];
2394 if( mbpc->rank() == 0 ) std::cout <<
"Initializing zoltan..." << std::endl;
2399 if( NULL ==
myZZ )
myZZ =
new Zoltan( mbpc->comm() );
2403 sprintf( buff,
"%d", numNewPartitions );
2404 int retval =
myZZ->Set_Param(
"NUM_GLOBAL_PARTITIONS", buff );
2405 if( ZOLTAN_OK != retval )
return MB_FAILURE;
2408 retval =
myZZ->Set_Param(
"RETURN_LISTS",
"PARTS" );
2409 if( ZOLTAN_OK != retval )
return MB_FAILURE;
2433 ZOLTAN_ID_PTR import_global_ids, import_local_ids;
2435 int* import_to_part;
2437 ZOLTAN_ID_PTR export_global_ids, export_local_ids;
2438 int *assign_procs, *assign_parts;
2440 if( mbpc->rank() == 0 )
2441 std::cout <<
"Computing partition using method (1-graph, 2-geom):" << met <<
" for " << numNewPartitions
2442 <<
" parts..." << std::endl;
2446 static int counter=0;
2449 std::stringstream basename;
2452 basename <<
"phg_" << counter++;
2453 Zoltan_Generate_Files(
myZZ->Get_C_Handle(), (
char*)(basename.str().c_str()), 1, 0, 1, 0);
2457 basename <<
"rcb_" << counter++;
2458 Zoltan_Generate_Files(
myZZ->Get_C_Handle(), (
char*)(basename.str().c_str()), 1, 1, 0, 0);
2462 retval =
myZZ->LB_Partition( changes, numGidEntries, numLidEntries, num_import, import_global_ids, import_local_ids,
2463 import_procs, import_to_part, num_export, export_global_ids, export_local_ids,
2464 assign_procs, assign_parts );
2465 if( ZOLTAN_OK != retval )
return MB_FAILURE;
2468 std::stringstream ff3;
2469 ff3 <<
"zoltanOutput_" << mbpc->rank() <<
".txt";
2471 ofs3.open( ff3.str().c_str(), std::ofstream::out );
2472 ofs3 <<
" export elements on rank " << rank <<
" \n";
2473 ofs3 <<
"\t index \t gb_id \t local \t proc \t part \n";
2474 for(
int k = 0; k < num_export; k++ )
2476 ofs3 <<
"\t" << k <<
"\t" << export_global_ids[k] <<
"\t" << export_local_ids[k] <<
"\t" << assign_procs[k]
2477 <<
"\t" << assign_parts[k] <<
"\n";
2484 assert( num_export == (
int)primary.
size() );
2485 for( i = 0; i < num_export; i++ )
2488 distribution[assign_parts[i]].
insert( cell );
2491 Zoltan::LB_Free_Part( &import_global_ids, &import_local_ids, &import_procs, &import_to_part );
2492 Zoltan::LB_Free_Part( &export_global_ids, &export_local_ids, &assign_procs, &assign_parts );
2499 std::vector< int >().swap( adjacencies );
2500 std::vector< int >().swap( ids );
2501 std::vector< int >().swap(
length );
2502 std::vector< int >().swap( nbor_proc );
2503 std::vector< double >().swap( coords );