MOAB: Mesh Oriented datABase  (version 5.2.1)
mbpart.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines