MOAB: Mesh Oriented datABase
(version 5.2.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 <stdlib.h> 00030 #include <list> 00031 #include <time.h> 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", "use spherical coordinates (1) or gnomonic projection (2) for partitioning ", &projection_type ); 00172 #ifdef MOAB_HAVE_METIS 00173 bool partition_tagged_sets = false; 00174 opts.addOpt< void >( "taggedsets,x", "(Metis) Partition tagged sets.", &partition_tagged_sets ); 00175 00176 bool partition_tagged_ents = false; 00177 opts.addOpt< void >( "taggedents,y", "(Metis) Partition tagged ents.", &partition_tagged_ents ); 00178 00179 std::string aggregating_tag; 00180 opts.addOpt< std::string >( "aggregatingtag,a", 00181 "(Metis) Specify aggregating tag to partion tagged sets or tagged entities.", 00182 &aggregating_tag ); 00183 00184 std::string aggregating_bc_tag; 00185 opts.addOpt< std::string >( "aggregatingBCtag,B", 00186 "(Metis) Specify boundary id tag name used to group cells with same boundary ids.", 00187 &aggregating_bc_tag ); 00188 00189 std::string boundaryIds; 00190 std::vector< int > BCids; 00191 opts.addOpt< std::string >( "aggregatingBCids,I", 00192 " (Metis) Specify id or ids of boundaries to be aggregated before " 00193 "partitioning (all elements with same boundary id will be in the " 00194 "same partition). Comma separated e.g. -I 1,2,5 ", 00195 &boundaryIds ); 00196 #endif // MOAB_HAVE_METIS 00197 00198 bool assign_global_ids = false; 00199 opts.addOpt< void >( "globalIds,j", "Assign GLOBAL_ID tag to entities", &assign_global_ids ); 00200 00201 opts.parseCommandLine( argc, argv ); 00202 00203 #ifdef MOAB_HAVE_ZOLTAN 00204 if( !zoltan_method.empty() ) 00205 moab_use_zoltan = true; 00206 else 00207 #endif 00208 #ifdef MOAB_HAVE_METIS 00209 if( !metis_method.empty() ) 00210 moab_use_metis = true; 00211 else 00212 #endif 00213 MB_SET_ERR( MB_FAILURE, "Specify either Zoltan or Metis partitioner type" ); 00214 00215 #ifdef MOAB_HAVE_ZOLTAN 00216 ZoltanPartitioner* zoltan_tool = NULL; 00217 // check if partition geometry, if it is, should get mesh size for the geometry 00218 if( part_geom_mesh_size != -1.0 && part_geom_mesh_size <= 0.0 ) 00219 { 00220 std::cerr << part_geom_mesh_size << ": invalid geometry partition mesh size." << std::endl << std::endl; 00221 opts.printHelp(); 00222 return EXIT_FAILURE; 00223 } 00224 00225 if( slave_file_name.size() ) moab_partition_slave = true; 00226 00227 if( moab_use_zoltan ) 00228 { 00229 if( part_geom_mesh_size < 0. ) 00230 { 00231 // partition mesh 00232 zoltan_tool = new ZoltanPartitioner( &mb, false, argc, argv ); 00233 } 00234 else 00235 { 00236 // partition geometry 00237 #ifdef MOAB_HAVE_CGM 00238 CubitStatus status = InitCGMA::initialize_cgma(); 00239 if( CUBIT_SUCCESS != status ) 00240 { 00241 std::cerr << "CGM couldn't be initialized." << std::endl << std::endl; 00242 opts.printHelp(); 00243 return EXIT_FAILURE; 00244 } 00245 GeometryQueryTool* gti = GeometryQueryTool::instance(); 00246 zoltan_tool = new ZoltanPartitioner( &mb, false, argc, argv, gti ); 00247 #else 00248 std::cerr << "CGM should be configured to partition geometry." << std::endl << std::endl; 00249 opts.printHelp(); 00250 return EXIT_FAILURE; 00251 #endif // MOAB_HAVE_CGM 00252 } 00253 zoltan_tool->set_global_id_option( assign_global_ids ); 00254 } 00255 00256 if( zoltan_method.empty() && parm_method.empty() && oct_method.empty() ) zoltan_method = DEFAULT_ZOLTAN_METHOD; 00257 if( !parm_method.empty() ) zoltan_method = ZOLTAN_PARMETIS_METHOD; 00258 if( !oct_method.empty() ) zoltan_method = ZOLTAN_OCTPART_METHOD; 00259 #endif // MOAB_HAVE_ZOLTAN 00260 00261 #ifdef MOAB_HAVE_METIS 00262 MetisPartitioner* metis_tool = NULL; 00263 if( moab_use_metis && !metis_tool ) 00264 { 00265 metis_tool = new MetisPartitioner( &mb, false ); 00266 metis_tool->set_global_id_option( assign_global_ids ); 00267 } 00268 00269 if( ( aggregating_tag.empty() && partition_tagged_sets ) || ( aggregating_tag.empty() && partition_tagged_ents ) ) 00270 aggregating_tag = DEFAULT_TAGGEDSETS_TAG; 00271 if( !write_sets && !write_tags ) write_sets = true; 00272 00273 if( !boundaryIds.empty() ) 00274 { 00275 std::vector< std::string > ids; 00276 std::stringstream ss( boundaryIds ); 00277 std::string item; 00278 while( std::getline( ss, item, ',' ) ) 00279 { 00280 ids.push_back( item ); 00281 } 00282 for( unsigned int i = 0; i < ids.size(); i++ ) 00283 BCids.push_back( std::atoi( ids[i].c_str() ) ); 00284 } 00285 00286 if( metis_method.empty() ) { metis_method = METIS_DEFAULT_METHOD; } 00287 00288 #endif // MOAB_HAVE_METIS 00289 00290 if( !write_sets && !write_tags ) write_sets = true; 00291 00292 if( -1 == power ) 00293 { 00294 num_parts = opts.getReqArg< int >( "#parts" ); 00295 power = 1; 00296 } 00297 else if( power < 1 || power > 18 ) 00298 { 00299 std::cerr << power << ": invalid power for multiple partitions. Expected value in [1,18]" << std::endl 00300 << std::endl; 00301 opts.printHelp(); 00302 return EXIT_FAILURE; 00303 } 00304 else 00305 { 00306 num_parts = 2; 00307 } 00308 00309 if( part_dim < 0 || part_dim > 3 ) 00310 { 00311 std::cerr << part_dim << " : invalid dimension" << std::endl << std::endl; 00312 opts.printHelp(); 00313 return EXIT_FAILURE; 00314 } 00315 00316 if( imbal_tol < 0.0 ) 00317 { 00318 std::cerr << imbal_tol << ": invalid imbalance tolerance" << std::endl << std::endl; 00319 opts.printHelp(); 00320 return EXIT_FAILURE; 00321 } 00322 00323 bool load_msets = false; 00324 if( opts.getOpt( "set_l,l", &set_l ) ) 00325 { 00326 load_msets = true; 00327 if( set_l.size() <= 0 ) 00328 { 00329 std::cerr << " No material set id's to load" << std::endl << std::endl; 00330 opts.printHelp(); 00331 return EXIT_FAILURE; 00332 } 00333 } 00334 00335 if( num_parts <= 1 ) 00336 { 00337 std::cerr << "** Please specify #parts = " << num_parts << " to be greater than 1." << std::endl << std::endl; 00338 opts.printHelp(); 00339 return EXIT_FAILURE; 00340 } 00341 00342 clock_t t = clock(); 00343 00344 const char* options = NULL; 00345 ErrorCode rval; 00346 #ifdef MOAB_HAVE_ZOLTAN 00347 if( part_geom_mesh_size > 0. ) options = "FACET_DISTANCE_TOLERANCE=0.1"; 00348 #endif // MOAB_HAVE_ZOLTAN 00349 00350 std::cout << "Loading file " << input_file << "..." << std::endl; 00351 if( load_msets == false ) 00352 { 00353 rval = mb.load_file( input_file.c_str(), 0, options );MB_CHK_SET_ERR( rval, "Failed to load input file: " + input_file ); 00354 } 00355 else // load the material set(s) 00356 { 00357 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 ); 00358 } 00359 if( print_time ) 00360 std::cout << "Read input file in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl; 00361 00362 for( int dim = part_dim; dim >= 0; --dim ) 00363 { 00364 int n; 00365 rval = mb.get_number_entities_by_dimension( 0, dim, n ); 00366 if( MB_SUCCESS == rval && 0 != n ) 00367 { 00368 part_dim = dim; 00369 break; 00370 } 00371 } 00372 if( part_dim < 0 ) 00373 { 00374 std::cerr << input_file << " : file does not contain any mesh entities" << std::endl; 00375 return 2; 00376 } 00377 00378 ReorderTool reorder_tool( &moab ); 00379 00380 for( int p = 0; p < power; p++ ) 00381 { 00382 t = clock(); 00383 #ifdef MOAB_HAVE_ZOLTAN 00384 if( moab_use_zoltan ) 00385 { 00386 rval = zoltan_tool->partition_mesh_and_geometry( 00387 part_geom_mesh_size, num_parts, zoltan_method.c_str(), 00388 ( !parm_method.empty() ? parm_method.c_str() : oct_method.c_str() ), imbal_tol, part_dim, write_sets, 00389 write_tags, obj_weight, edge_weight, part_surf, ghost, projection_type, recompute_box_rcb, print_time );MB_CHK_SET_ERR( rval, "Zoltan partitioner failed." ); 00390 } 00391 #endif 00392 #ifdef MOAB_HAVE_METIS 00393 if( moab_use_metis ) 00394 { 00395 rval = metis_tool->partition_mesh( num_parts, metis_method.c_str(), part_dim, write_sets, write_tags, 00396 partition_tagged_sets, partition_tagged_ents, aggregating_tag.c_str(), 00397 print_time );MB_CHK_SET_ERR( rval, "Metis partitioner failed." ); 00398 } 00399 #endif 00400 00401 if( print_time ) 00402 std::cout << "Generated " << num_parts << " part partitioning in " 00403 << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl; 00404 00405 if( reorder && part_geom_mesh_size < 0. ) 00406 { 00407 std::cout << "Reordering mesh for partition..." << std::endl; 00408 00409 Tag tag, order; 00410 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" ); 00411 00412 t = clock(); 00413 if( write_sets ) 00414 { 00415 Range sets; 00416 mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, sets ); 00417 rval = reorder_tool.handle_order_from_sets_and_adj( sets, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." ); 00418 } 00419 else 00420 { 00421 rval = reorder_tool.handle_order_from_int_tag( tag, -1, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." ); 00422 } 00423 00424 rval = reorder_tool.reorder_entities( order );MB_CHK_SET_ERR( rval, "Failed to perform reordering." ); 00425 00426 rval = mb.tag_delete( order );MB_CHK_SET_ERR( rval, "Failed to delete tag." ); 00427 if( print_time ) 00428 std::cout << "Reordered mesh in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" 00429 << std::endl; 00430 } 00431 00432 #ifdef MOAB_HAVE_ZOLTAN 00433 if( incl_closure ) 00434 { 00435 rval = zoltan_tool->include_closure();MB_CHK_SET_ERR( rval, "Closure inclusion failed." ); 00436 } 00437 #endif 00438 00439 std::ostringstream tmp_output_file; 00440 00441 if( power > 1 ) 00442 { 00443 // append num_parts to output filename 00444 std::string::size_type idx = output_file.find_last_of( "." ); 00445 if( idx == std::string::npos ) 00446 { 00447 tmp_output_file << output_file << "_" << num_parts; 00448 if( part_geom_mesh_size < 0. ) 00449 tmp_output_file << ".h5m"; 00450 else 00451 { 00452 std::cerr << "output file type is not specified." << std::endl; 00453 return 1; 00454 } 00455 } 00456 else 00457 { 00458 tmp_output_file << output_file.substr( 0, idx ) << "_" << num_parts << output_file.substr( idx ); 00459 } 00460 } 00461 else 00462 tmp_output_file << output_file; 00463 00464 t = clock(); 00465 std::cout << "Saving file to " << output_file << "..." << std::endl; 00466 if( part_geom_mesh_size < 0. ) 00467 { 00468 rval = mb.write_file( tmp_output_file.str().c_str() ); 00469 if( MB_SUCCESS != rval ) 00470 { 00471 std::cerr << tmp_output_file.str() << " : failed to write file." << std::endl; 00472 std::cerr << " Error code: " << mb.get_error_string( rval ) << " (" << rval << ")" << std::endl; 00473 std::string errstr; 00474 mb.get_last_error( errstr ); 00475 if( !errstr.empty() ) std::cerr << " Error message: " << errstr << std::endl; 00476 return 2; 00477 } 00478 } 00479 #ifdef MOAB_HAVE_ZOLTAN 00480 #ifdef MOAB_HAVE_CGM 00481 else 00482 { 00483 std::string::size_type idx = output_file.find_last_of( "." ); 00484 int c_size = output_file.length() - idx; 00485 const char* file_type = NULL; 00486 if( output_file.compare( idx, c_size, ".occ" ) == 0 || output_file.compare( idx, c_size, ".OCC" ) == 0 ) 00487 file_type = "OCC"; 00488 else if( output_file.compare( idx, c_size, ".sab" ) == 0 ) 00489 file_type = "ACIS_SAB"; 00490 else if( output_file.compare( idx, c_size, ".sat" ) == 0 ) 00491 file_type = "ACIS_SAT"; 00492 else 00493 { 00494 std::cerr << "File type for " << output_file.c_str() << " not supported." << std::endl; 00495 return 1; 00496 } 00497 00498 int num_ents_exported = 0; 00499 DLIList< RefEntity* > ref_entity_list; 00500 CubitStatus status = 00501 CubitCompat_export_solid_model( ref_entity_list, tmp_output_file.str().c_str(), file_type, 00502 num_ents_exported, CubitString( __FILE__ ) ); 00503 if( CUBIT_SUCCESS != status ) 00504 { 00505 std::cerr << "CGM couldn't export models." << std::endl; 00506 return 1; 00507 } 00508 } 00509 #endif 00510 #endif 00511 00512 if( print_time ) 00513 std::cout << "Wrote \"" << tmp_output_file.str() << "\" in " << ( clock() - t ) / (double)CLOCKS_PER_SEC 00514 << " seconds" << std::endl; 00515 00516 #ifdef MOAB_HAVE_ZOLTAN 00517 00518 if( moab_use_zoltan && moab_partition_slave && p == 0 ) 00519 { 00520 t = clock(); 00521 double master_radius, slave_radius; 00522 if( rescale_spherical_radius ) 00523 { 00524 EntityHandle rootset = 0; 00525 Range masterverts; 00526 rval = mb.get_entities_by_dimension( rootset, 0, masterverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" ); 00527 double points[6]; 00528 EntityHandle mfrontback[2] = { masterverts[0], masterverts[masterverts.size() - 1] }; 00529 rval = mb.get_coords( &mfrontback[0], 2, points );MB_CHK_ERR( rval ); 00530 const double mr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] ); 00531 const double mr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] ); 00532 master_radius = 0.5 * ( mr1 + mr2 ); 00533 } 00534 EntityHandle slaveset; 00535 rval = mb.create_meshset( moab::MESHSET_SET, slaveset );MB_CHK_SET_ERR( rval, "Can't create new set" ); 00536 rval = mb.load_file( slave_file_name.c_str(), &slaveset, options );MB_CHK_SET_ERR( rval, "Can't load slave mesh" ); 00537 if( rescale_spherical_radius ) 00538 { 00539 double points[6]; 00540 Range slaveverts; 00541 rval = mb.get_entities_by_dimension( slaveset, 0, slaveverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" ); 00542 EntityHandle sfrontback[2] = { slaveverts[0], slaveverts[slaveverts.size() - 1] }; 00543 rval = mb.get_coords( &sfrontback[0], 2, points );MB_CHK_ERR( rval ); 00544 const double sr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] ); 00545 const double sr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] ); 00546 slave_radius = 0.5 * ( sr1 + sr2 ); 00547 // Let us rescale both master and slave meshes to a unit sphere 00548 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, master_radius );MB_CHK_ERR( rval ); 00549 } 00550 00551 rval = zoltan_tool->partition_inferred_mesh( slaveset, num_parts, part_dim, write_sets, projection_type );MB_CHK_ERR( rval ); 00552 00553 if( rescale_spherical_radius ) 00554 { 00555 // rescale the slave mesh back to its original radius 00556 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, slave_radius );MB_CHK_ERR( rval ); 00557 } 00558 00559 if( print_time ) 00560 { 00561 std::cout << "Time taken to infer slave mesh partitions = " << ( clock() - t ) / (double)CLOCKS_PER_SEC 00562 << " seconds" << std::endl; 00563 } 00564 00565 size_t lastindex = slave_file_name.find_last_of( "." ); 00566 std::string inferred_output_file = slave_file_name.substr( 0, lastindex ) + "_inferred" + 00567 slave_file_name.substr( lastindex, slave_file_name.size() ); 00568 00569 // Save the resulting mesh 00570 std::cout << "Saving inferred file to " << inferred_output_file << "..." << std::endl; 00571 rval = mb.write_file( inferred_output_file.c_str(), 0, 0, &slaveset, 1 ); 00572 if( MB_SUCCESS != rval ) 00573 { 00574 std::cerr << tmp_output_file.str() << " : failed to write file." << std::endl; 00575 std::cerr << " Error code: " << mb.get_error_string( rval ) << " (" << rval << ")" << std::endl; 00576 std::string errstr; 00577 mb.get_last_error( errstr ); 00578 if( !errstr.empty() ) std::cerr << " Error message: " << errstr << std::endl; 00579 return 2; 00580 } 00581 } 00582 #endif 00583 00584 num_parts *= 2; 00585 } 00586 00587 #ifdef MOAB_HAVE_ZOLTAN 00588 delete zoltan_tool; 00589 #endif 00590 #ifdef MOAB_HAVE_METIS 00591 delete metis_tool; 00592 #endif 00593 00594 #ifdef MOAB_HAVE_MPI 00595 err = MPI_Finalize(); 00596 assert( MPI_SUCCESS == err ); 00597 #endif 00598 return 0; 00599 }