![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00027 #include
00028 #include
00029 #include
00030 #include
00031 #include
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 }