MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/Core.hpp" 00002 #include "moab/ProgOptions.hpp" 00003 #include "moab/ReorderTool.hpp" 00004 00005 #ifdef MOAB_HAVE_MPI 00006 #include "moab/ParallelComm.hpp" 00007 #endif 00008 00009 #ifdef MOAB_HAVE_ZOLTAN 00010 #include "moab/ZoltanPartitioner.hpp" 00011 00012 #ifdef MOAB_HAVE_CGM 00013 #include "InitCGMA.hpp" 00014 #include "CubitCompat.hpp" 00015 #endif 00016 00017 #endif 00018 00019 #ifdef MOAB_HAVE_METIS 00020 #include "moab/MetisPartitioner.hpp" 00021 typedef idx_t PartType; 00022 #else 00023 typedef int PartType; 00024 #endif 00025 00026 #include <iostream> 00027 #include <sstream> 00028 #include <cmath> 00029 #include <cstdlib> 00030 #include <list> 00031 #include <ctime> 00032 00033 #include "moab/IntxMesh/IntxUtils.hpp" 00034 00035 using namespace moab; 00036 00037 std::string DEFAULT_TAGGEDSETS_TAG = "PARALLEL_PARTITION"; 00038 00039 const char DEFAULT_ZOLTAN_METHOD[] = "RCB"; 00040 #ifdef MOAB_HAVE_ZOLTAN 00041 const char ZOLTAN_PARMETIS_METHOD[] = "PARMETIS"; 00042 const char ZOLTAN_OCTPART_METHOD[] = "OCTPART"; 00043 #endif 00044 00045 const char METIS_DEFAULT_METHOD[] = "ML_KWAY"; 00046 /* const char METIS_ALTERNATIVE_METHOD[] = "ML_RB"; */ 00047 00048 const char BRIEF_DESC[] = "Use Zoltan or Metis to partition MOAB meshes for use on parallel computers"; 00049 std::ostringstream LONG_DESC; 00050 00051 int main( int argc, char* argv[] ) 00052 { 00053 #ifdef MOAB_HAVE_MPI 00054 int err = MPI_Init( &argc, &argv ); 00055 if( err ) 00056 { 00057 std::cerr << "MPI_Init failed. Aborting." << std::endl; 00058 return 3; 00059 } 00060 #endif 00061 Core moab; 00062 Interface& mb = moab; 00063 std::vector< int > set_l; 00064 00065 #ifdef MOAB_HAVE_ZOLTAN 00066 bool moab_use_zoltan = false; 00067 #endif 00068 #ifdef MOAB_HAVE_METIS 00069 bool moab_use_metis = false; 00070 #endif 00071 00072 LONG_DESC << "This utility invokes the ZoltanPartitioner or MetisPartitioner component of MOAB/CGM " 00073 "to partition a mesh/geometry." 00074 << std::endl 00075 << "If no partitioning method is specified, the defaults are: " 00076 << "for Zoltan=\"" << DEFAULT_ZOLTAN_METHOD << "\" and Metis=\"" << METIS_DEFAULT_METHOD << " method" 00077 << std::endl; 00078 00079 ProgOptions opts( LONG_DESC.str(), BRIEF_DESC ); 00080 00081 int part_dim = 3; 00082 opts.addOpt< int >( "dimension", 00083 "Specify dimension of entities to partition." 00084 " Default is largest in file.", 00085 &part_dim, ProgOptions::int_flag ); 00086 00087 std::string zoltan_method, parm_method, oct_method, metis_method; 00088 #ifdef MOAB_HAVE_ZOLTAN 00089 opts.addOpt< std::string >( "zoltan,z", 00090 "(Zoltan) Specify Zoltan partition method. " 00091 "One of RR, RCB, RIB, HFSC, PHG, or Hypergraph (PHG and Hypergraph " 00092 "are synonymous).", 00093 &zoltan_method ); 00094 #ifdef MOAB_HAVE_PARMETIS 00095 opts.addOpt< std::string >( "parmetis,p", "(Zoltan+PARMetis) Specify PARMetis partition method.", &parm_method ); 00096 #endif // MOAB_HAVE_PARMETIS 00097 opts.addOpt< std::string >( "octpart,o", "(Zoltan) Specify OctPart partition method.", &oct_method ); 00098 00099 bool incl_closure = false; 00100 opts.addOpt< void >( "include_closure,c", "Include element closure for part sets.", &incl_closure ); 00101 00102 bool recompute_box_rcb = false; 00103 opts.addOpt< void >( "recompute_rcb_box,b", "recompute box in rcb cuts", &recompute_box_rcb ); 00104 #endif // MOAB_HAVE_ZOLTAN 00105 00106 double imbal_tol = 1.03; 00107 opts.addOpt< double >( "imbalance,i", "Imbalance tolerance (used in PHG/Hypergraph method)", &imbal_tol ); 00108 00109 #ifdef MOAB_HAVE_METIS 00110 opts.addOpt< std::string >( "metis,m", "(Metis) Specify Metis partition method. One of ML_RB or ML_KWAY.", 00111 &metis_method ); 00112 #endif // MOAB_HAVE_METIS 00113 00114 bool write_sets = true, write_tags = false; 00115 opts.addOpt< void >( "sets,s", "Write partition as tagged sets (Default)", &write_sets ); 00116 opts.addOpt< void >( "tags,t", "Write partition by tagging entities", &write_tags ); 00117 00118 int power = -1; 00119 opts.addOpt< int >( "power,M", "Generate multiple partitions, in powers of 2, up to 2^(pow)", &power ); 00120 00121 bool reorder = false; 00122 opts.addOpt< void >( "reorder,R", "Reorder mesh to group entities by partition", &reorder ); 00123 00124 double part_geom_mesh_size = -1.0; 00125 #ifdef MOAB_HAVE_ZOLTAN 00126 bool part_surf = false; 00127 #ifdef MOAB_HAVE_CGM 00128 opts.addOpt< double >( "geom,g", "(CGM) If partition geometry, specify mesh size.", &part_geom_mesh_size ); 00129 opts.addOpt< void >( "surf,f", "(CGM) Specify if partition geometry surface.", &part_surf ); 00130 #endif // MOAB_HAVE_CGM 00131 00132 bool ghost = false; 00133 opts.addOpt< void >( "ghost,H", "(Zoltan) Specify if partition ghost geometry body." ); 00134 00135 int obj_weight = 0; 00136 opts.addOpt< int >( "vertex_w,v", "(Zoltan) Number of weights associated with a graph vertex." ); 00137 00138 int edge_weight = 0; 00139 opts.addOpt< int >( "edge_w,e", "(Zoltan) Number of weights associated with an edge." ); 00140 00141 bool moab_partition_slave = false; 00142 std::string slave_file_name = ""; 00143 opts.addOpt< std::string >( "inferred", 00144 "(Zoltan) Specify inferred slave mesh file name to impose " 00145 "partition based on cuts computed for original master mesh.", 00146 &slave_file_name ); 00147 00148 bool rescale_spherical_radius = false; 00149 opts.addOpt< void >( "scale_sphere", 00150 "(Zoltan) If the meshes are defined on a sphere, rescale radius as needed " 00151 "(in combination with --inferred)", 00152 &rescale_spherical_radius ); 00153 00154 #endif // MOAB_HAVE_ZOLTAN 00155 00156 long num_parts; 00157 opts.addOpt< std::vector< int > >( "set_l,l", 00158 "Load material set(s) with specified ids (comma separated) for partition" ); 00159 00160 opts.addRequiredArg< int >( "#parts", "Number of parts in partition" ); 00161 00162 std::string input_file, output_file; 00163 opts.addRequiredArg< std::string >( "input_file", "Mesh/geometry to partition", &input_file ); 00164 opts.addRequiredArg< std::string >( "output_file", "File to which to write partitioned mesh/geometry", 00165 &output_file ); 00166 00167 bool print_time = false; 00168 opts.addOpt< void >( ",T", "Print CPU time for each phase.", &print_time ); 00169 00170 int projection_type = 0; 00171 opts.addOpt< int >( "project_on_sphere,p", 00172 "use spherical coordinates (1) or gnomonic projection (2) for partitioning ", 00173 &projection_type ); 00174 #ifdef MOAB_HAVE_METIS 00175 bool partition_tagged_sets = false; 00176 opts.addOpt< void >( "taggedsets,x", "(Metis) Partition tagged sets.", &partition_tagged_sets ); 00177 00178 bool partition_tagged_ents = false; 00179 opts.addOpt< void >( "taggedents,y", "(Metis) Partition tagged ents.", &partition_tagged_ents ); 00180 00181 std::string aggregating_tag; 00182 opts.addOpt< std::string >( "aggregatingtag,a", 00183 "(Metis) Specify aggregating tag to partion tagged sets or tagged entities.", 00184 &aggregating_tag ); 00185 00186 std::string aggregating_bc_tag; 00187 opts.addOpt< std::string >( "aggregatingBCtag,B", 00188 "(Metis) Specify boundary id tag name used to group cells with same boundary ids.", 00189 &aggregating_bc_tag ); 00190 00191 std::string boundaryIds; 00192 std::vector< int > BCids; 00193 opts.addOpt< std::string >( "aggregatingBCids,I", 00194 " (Metis) Specify id or ids of boundaries to be aggregated before " 00195 "partitioning (all elements with same boundary id will be in the " 00196 "same partition). Comma separated e.g. -I 1,2,5 ", 00197 &boundaryIds ); 00198 #endif // MOAB_HAVE_METIS 00199 00200 bool assign_global_ids = false; 00201 opts.addOpt< void >( "globalIds,j", "Assign GLOBAL_ID tag to entities", &assign_global_ids ); 00202 00203 opts.parseCommandLine( argc, argv ); 00204 00205 #ifdef MOAB_HAVE_ZOLTAN 00206 if( !zoltan_method.empty() ) 00207 moab_use_zoltan = true; 00208 else 00209 #endif 00210 #ifdef MOAB_HAVE_METIS 00211 if( !metis_method.empty() ) 00212 moab_use_metis = true; 00213 else 00214 #endif 00215 MB_SET_ERR( MB_FAILURE, "Specify either Zoltan or Metis partitioner type" ); 00216 00217 #ifdef MOAB_HAVE_ZOLTAN 00218 ZoltanPartitioner* zoltan_tool = NULL; 00219 // check if partition geometry, if it is, should get mesh size for the geometry 00220 if( part_geom_mesh_size != -1.0 && part_geom_mesh_size <= 0.0 ) 00221 { 00222 std::cerr << part_geom_mesh_size << ": invalid geometry partition mesh size." << std::endl << std::endl; 00223 opts.printHelp(); 00224 return EXIT_FAILURE; 00225 } 00226 00227 if( slave_file_name.size() ) moab_partition_slave = true; 00228 00229 if( moab_use_zoltan ) 00230 { 00231 if( part_geom_mesh_size < 0. ) 00232 { 00233 // partition mesh we have no ParallelComm here, so we will create one later 00234 zoltan_tool = new ZoltanPartitioner( &mb, NULL, false, argc, argv ); 00235 } 00236 else 00237 { 00238 // partition geometry 00239 #ifdef MOAB_HAVE_CGM 00240 CubitStatus status = InitCGMA::initialize_cgma(); 00241 if( CUBIT_SUCCESS != status ) 00242 { 00243 std::cerr << "CGM couldn't be initialized." << std::endl << std::endl; 00244 opts.printHelp(); 00245 return EXIT_FAILURE; 00246 } 00247 GeometryQueryTool* gti = GeometryQueryTool::instance(); 00248 // no ParallelComm so far 00249 zoltan_tool = new ZoltanPartitioner( &mb, NULL, false, argc, argv, gti ); 00250 #else 00251 std::cerr << "CGM should be configured to partition geometry." << std::endl << std::endl; 00252 opts.printHelp(); 00253 return EXIT_FAILURE; 00254 #endif // MOAB_HAVE_CGM 00255 } 00256 zoltan_tool->set_global_id_option( assign_global_ids ); 00257 } 00258 00259 if( zoltan_method.empty() && parm_method.empty() && oct_method.empty() ) zoltan_method = DEFAULT_ZOLTAN_METHOD; 00260 if( !parm_method.empty() ) zoltan_method = ZOLTAN_PARMETIS_METHOD; 00261 if( !oct_method.empty() ) zoltan_method = ZOLTAN_OCTPART_METHOD; 00262 #endif // MOAB_HAVE_ZOLTAN 00263 00264 #ifdef MOAB_HAVE_METIS 00265 MetisPartitioner* metis_tool = NULL; 00266 if( moab_use_metis && !metis_tool ) 00267 { 00268 metis_tool = new MetisPartitioner( &mb, false ); 00269 metis_tool->set_global_id_option( assign_global_ids ); 00270 } 00271 00272 if( ( aggregating_tag.empty() && partition_tagged_sets ) || ( aggregating_tag.empty() && partition_tagged_ents ) ) 00273 aggregating_tag = DEFAULT_TAGGEDSETS_TAG; 00274 if( !write_sets && !write_tags ) write_sets = true; 00275 00276 if( !boundaryIds.empty() ) 00277 { 00278 std::vector< std::string > ids; 00279 std::stringstream ss( boundaryIds ); 00280 std::string item; 00281 while( std::getline( ss, item, ',' ) ) 00282 { 00283 ids.push_back( item ); 00284 } 00285 for( unsigned int i = 0; i < ids.size(); i++ ) 00286 BCids.push_back( std::atoi( ids[i].c_str() ) ); 00287 } 00288 00289 if( metis_method.empty() ) 00290 { 00291 metis_method = METIS_DEFAULT_METHOD; 00292 } 00293 00294 #endif // MOAB_HAVE_METIS 00295 00296 if( !write_sets && !write_tags ) write_sets = true; 00297 00298 if( -1 == power ) 00299 { 00300 num_parts = opts.getReqArg< int >( "#parts" ); 00301 power = 1; 00302 } 00303 else if( power < 1 || power > 18 ) 00304 { 00305 std::cerr << power << ": invalid power for multiple partitions. Expected value in [1,18]" << std::endl 00306 << std::endl; 00307 opts.printHelp(); 00308 return EXIT_FAILURE; 00309 } 00310 else 00311 { 00312 num_parts = 2; 00313 } 00314 00315 if( part_dim < 0 || part_dim > 3 ) 00316 { 00317 std::cerr << part_dim << " : invalid dimension" << std::endl << std::endl; 00318 opts.printHelp(); 00319 return EXIT_FAILURE; 00320 } 00321 00322 if( imbal_tol < 0.0 ) 00323 { 00324 std::cerr << imbal_tol << ": invalid imbalance tolerance" << std::endl << std::endl; 00325 opts.printHelp(); 00326 return EXIT_FAILURE; 00327 } 00328 00329 bool load_msets = false; 00330 if( opts.getOpt( "set_l,l", &set_l ) ) 00331 { 00332 load_msets = true; 00333 if( set_l.size() <= 0 ) 00334 { 00335 std::cerr << " No material set id's to load" << std::endl << std::endl; 00336 opts.printHelp(); 00337 return EXIT_FAILURE; 00338 } 00339 } 00340 00341 if( num_parts <= 1 ) 00342 { 00343 std::cerr << "** Please specify #parts = " << num_parts << " to be greater than 1." << std::endl << std::endl; 00344 opts.printHelp(); 00345 return EXIT_FAILURE; 00346 } 00347 00348 clock_t t = clock(); 00349 00350 const char* options = NULL; 00351 ErrorCode rval; 00352 #ifdef MOAB_HAVE_ZOLTAN 00353 if( part_geom_mesh_size > 0. ) options = "FACET_DISTANCE_TOLERANCE=0.1"; 00354 #endif // MOAB_HAVE_ZOLTAN 00355 00356 std::cout << "Loading file " << input_file << "..." << std::endl; 00357 if( load_msets == false ) 00358 { 00359 rval = mb.load_file( input_file.c_str(), 0, options );MB_CHK_SET_ERR( rval, "Failed to load input file: " + input_file ); 00360 } 00361 else // load the material set(s) 00362 { 00363 rval = mb.load_mesh( input_file.c_str(), &set_l[0], (int)set_l.size() );MB_CHK_SET_ERR( rval, "Failed to load input mesh: " + input_file ); 00364 } 00365 if( print_time ) 00366 std::cout << "Read input file in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl; 00367 00368 for( int dim = part_dim; dim >= 0; --dim ) 00369 { 00370 int n; 00371 rval = mb.get_number_entities_by_dimension( 0, dim, n ); 00372 if( MB_SUCCESS == rval && 0 != n ) 00373 { 00374 part_dim = dim; 00375 break; 00376 } 00377 } 00378 if( part_dim < 0 ) 00379 { 00380 std::cerr << input_file << " : file does not contain any mesh entities" << std::endl; 00381 return 2; 00382 } 00383 00384 ReorderTool reorder_tool( &moab ); 00385 00386 for( int p = 0; p < power; p++ ) 00387 { 00388 t = clock(); 00389 #ifdef MOAB_HAVE_ZOLTAN 00390 if( moab_use_zoltan ) 00391 { 00392 rval = zoltan_tool->partition_mesh_and_geometry( 00393 part_geom_mesh_size, num_parts, zoltan_method.c_str(), 00394 ( !parm_method.empty() ? parm_method.c_str() : oct_method.c_str() ), imbal_tol, part_dim, write_sets, 00395 write_tags, obj_weight, edge_weight, part_surf, ghost, projection_type, recompute_box_rcb, print_time );MB_CHK_SET_ERR( rval, "Zoltan partitioner failed." ); 00396 } 00397 #endif 00398 #ifdef MOAB_HAVE_METIS 00399 if( moab_use_metis ) 00400 { 00401 rval = metis_tool->partition_mesh( num_parts, metis_method.c_str(), part_dim, write_sets, write_tags, 00402 partition_tagged_sets, partition_tagged_ents, aggregating_tag.c_str(), 00403 print_time );MB_CHK_SET_ERR( rval, "Metis partitioner failed." ); 00404 } 00405 #endif 00406 00407 if( print_time ) 00408 std::cout << "Generated " << num_parts << " part partitioning in " 00409 << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl; 00410 00411 if( reorder && part_geom_mesh_size < 0. ) 00412 { 00413 std::cout << "Reordering mesh for partition..." << std::endl; 00414 00415 Tag tag, order; 00416 rval = mb.tag_get_handle( DEFAULT_TAGGEDSETS_TAG.c_str(), 1, MB_TYPE_INTEGER, tag );MB_CHK_SET_ERR( rval, "Partitioner did not create " + DEFAULT_TAGGEDSETS_TAG + " tag" ); 00417 00418 t = clock(); 00419 if( write_sets ) 00420 { 00421 Range sets; 00422 mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, sets ); 00423 rval = reorder_tool.handle_order_from_sets_and_adj( sets, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." ); 00424 } 00425 else 00426 { 00427 rval = reorder_tool.handle_order_from_int_tag( tag, -1, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." ); 00428 } 00429 00430 rval = reorder_tool.reorder_entities( order );MB_CHK_SET_ERR( rval, "Failed to perform reordering." ); 00431 00432 rval = mb.tag_delete( order );MB_CHK_SET_ERR( rval, "Failed to delete tag." ); 00433 if( print_time ) 00434 std::cout << "Reordered mesh in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" 00435 << std::endl; 00436 } 00437 00438 #ifdef MOAB_HAVE_ZOLTAN 00439 if( incl_closure ) 00440 { 00441 rval = zoltan_tool->include_closure();MB_CHK_SET_ERR( rval, "Closure inclusion failed." ); 00442 } 00443 #endif 00444 00445 std::ostringstream tmp_output_file; 00446 00447 if( power > 1 ) 00448 { 00449 // append num_parts to output filename 00450 std::string::size_type idx = output_file.find_last_of( "." ); 00451 if( idx == std::string::npos ) 00452 { 00453 tmp_output_file << output_file << "_" << num_parts; 00454 if( part_geom_mesh_size < 0. ) 00455 tmp_output_file << ".h5m"; 00456 else 00457 { 00458 std::cerr << "output file type is not specified." << std::endl; 00459 return 1; 00460 } 00461 } 00462 else 00463 { 00464 tmp_output_file << output_file.substr( 0, idx ) << "_" << num_parts << output_file.substr( idx ); 00465 } 00466 } 00467 else 00468 tmp_output_file << output_file; 00469 00470 t = clock(); 00471 std::cout << "Saving file to " << output_file << "..." << std::endl; 00472 if( part_geom_mesh_size < 0. ) 00473 { 00474 rval = mb.write_file( tmp_output_file.str().c_str() );MB_CHK_SET_ERR( rval, tmp_output_file.str() << " : failed to write file." << std::endl ); 00475 } 00476 #ifdef MOAB_HAVE_ZOLTAN 00477 #ifdef MOAB_HAVE_CGM 00478 else 00479 { 00480 std::string::size_type idx = output_file.find_last_of( "." ); 00481 int c_size = output_file.length() - idx; 00482 const char* file_type = NULL; 00483 if( output_file.compare( idx, c_size, ".occ" ) == 0 || output_file.compare( idx, c_size, ".OCC" ) == 0 ) 00484 file_type = "OCC"; 00485 else if( output_file.compare( idx, c_size, ".sab" ) == 0 ) 00486 file_type = "ACIS_SAB"; 00487 else if( output_file.compare( idx, c_size, ".sat" ) == 0 ) 00488 file_type = "ACIS_SAT"; 00489 else 00490 { 00491 std::cerr << "File type for " << output_file.c_str() << " not supported." << std::endl; 00492 return 1; 00493 } 00494 00495 int num_ents_exported = 0; 00496 DLIList< RefEntity* > ref_entity_list; 00497 CubitStatus status = 00498 CubitCompat_export_solid_model( ref_entity_list, tmp_output_file.str().c_str(), file_type, 00499 num_ents_exported, CubitString( __FILE__ ) ); 00500 if( CUBIT_SUCCESS != status ) 00501 { 00502 std::cerr << "CGM couldn't export models." << std::endl; 00503 return 1; 00504 } 00505 } 00506 #endif 00507 #endif 00508 00509 if( print_time ) 00510 std::cout << "Wrote \"" << tmp_output_file.str() << "\" in " << ( clock() - t ) / (double)CLOCKS_PER_SEC 00511 << " seconds" << std::endl; 00512 00513 #ifdef MOAB_HAVE_ZOLTAN 00514 00515 if( moab_use_zoltan && moab_partition_slave && p == 0 ) 00516 { 00517 t = clock(); 00518 double master_radius, slave_radius; 00519 if( rescale_spherical_radius ) 00520 { 00521 EntityHandle rootset = 0; 00522 Range masterverts; 00523 rval = mb.get_entities_by_dimension( rootset, 0, masterverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" ); 00524 double points[6]; 00525 EntityHandle mfrontback[2] = { masterverts[0], masterverts[masterverts.size() - 1] }; 00526 rval = mb.get_coords( &mfrontback[0], 2, points );MB_CHK_ERR( rval ); 00527 const double mr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] ); 00528 const double mr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] ); 00529 master_radius = 0.5 * ( mr1 + mr2 ); 00530 } 00531 EntityHandle slaveset; 00532 rval = mb.create_meshset( moab::MESHSET_SET, slaveset );MB_CHK_SET_ERR( rval, "Can't create new set" ); 00533 rval = mb.load_file( slave_file_name.c_str(), &slaveset, options );MB_CHK_SET_ERR( rval, "Can't load slave mesh" ); 00534 if( rescale_spherical_radius ) 00535 { 00536 double points[6]; 00537 Range slaveverts; 00538 rval = mb.get_entities_by_dimension( slaveset, 0, slaveverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" ); 00539 EntityHandle sfrontback[2] = { slaveverts[0], slaveverts[slaveverts.size() - 1] }; 00540 rval = mb.get_coords( &sfrontback[0], 2, points );MB_CHK_ERR( rval ); 00541 const double sr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] ); 00542 const double sr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] ); 00543 slave_radius = 0.5 * ( sr1 + sr2 ); 00544 // Let us rescale both master and slave meshes to a unit sphere 00545 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, master_radius );MB_CHK_ERR( rval ); 00546 } 00547 00548 rval = zoltan_tool->partition_inferred_mesh( slaveset, num_parts, part_dim, write_sets, projection_type );MB_CHK_ERR( rval ); 00549 00550 if( rescale_spherical_radius ) 00551 { 00552 // rescale the slave mesh back to its original radius 00553 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, slave_radius );MB_CHK_ERR( rval ); 00554 } 00555 00556 if( print_time ) 00557 { 00558 std::cout << "Time taken to infer slave mesh partitions = " << ( clock() - t ) / (double)CLOCKS_PER_SEC 00559 << " seconds" << std::endl; 00560 } 00561 00562 size_t lastindex = slave_file_name.find_last_of( "." ); 00563 std::string inferred_output_file = slave_file_name.substr( 0, lastindex ) + "_inferred" + 00564 slave_file_name.substr( lastindex, slave_file_name.size() ); 00565 00566 // Save the resulting mesh 00567 std::cout << "Saving inferred file to " << inferred_output_file << "..." << std::endl; 00568 rval = mb.write_file( inferred_output_file.c_str(), 0, 0, &slaveset, 1 );MB_CHK_SET_ERR( rval, inferred_output_file << " : failed to write file." << std::endl ); 00569 } 00570 #endif 00571 00572 num_parts *= 2; 00573 } 00574 00575 #ifdef MOAB_HAVE_ZOLTAN 00576 delete zoltan_tool; 00577 #endif 00578 #ifdef MOAB_HAVE_METIS 00579 delete metis_tool; 00580 #endif 00581 00582 #ifdef MOAB_HAVE_MPI 00583 err = MPI_Finalize(); 00584 assert( MPI_SUCCESS == err ); 00585 #endif 00586 return 0; 00587 }