MOAB: Mesh Oriented datABase  (version 5.4.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 <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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines