MOAB: Mesh Oriented datABase  (version 5.3.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
00234             zoltan_tool = new ZoltanPartitioner( &mb, 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             zoltan_tool            = new ZoltanPartitioner( &mb, false, argc, argv, gti );
00249 #else
00250             std::cerr << "CGM should be configured to partition geometry." << std::endl << std::endl;
00251             opts.printHelp();
00252             return EXIT_FAILURE;
00253 #endif  // MOAB_HAVE_CGM
00254         }
00255         zoltan_tool->set_global_id_option( assign_global_ids );
00256     }
00257 
00258     if( zoltan_method.empty() && parm_method.empty() && oct_method.empty() ) zoltan_method = DEFAULT_ZOLTAN_METHOD;
00259     if( !parm_method.empty() ) zoltan_method = ZOLTAN_PARMETIS_METHOD;
00260     if( !oct_method.empty() ) zoltan_method = ZOLTAN_OCTPART_METHOD;
00261 #endif  // MOAB_HAVE_ZOLTAN
00262 
00263 #ifdef MOAB_HAVE_METIS
00264     MetisPartitioner* metis_tool = NULL;
00265     if( moab_use_metis && !metis_tool )
00266     {
00267         metis_tool = new MetisPartitioner( &mb, false );
00268         metis_tool->set_global_id_option( assign_global_ids );
00269     }
00270 
00271     if( ( aggregating_tag.empty() && partition_tagged_sets ) || ( aggregating_tag.empty() && partition_tagged_ents ) )
00272         aggregating_tag = DEFAULT_TAGGEDSETS_TAG;
00273     if( !write_sets && !write_tags ) write_sets = true;
00274 
00275     if( !boundaryIds.empty() )
00276     {
00277         std::vector< std::string > ids;
00278         std::stringstream ss( boundaryIds );
00279         std::string item;
00280         while( std::getline( ss, item, ',' ) )
00281         {
00282             ids.push_back( item );
00283         }
00284         for( unsigned int i = 0; i < ids.size(); i++ )
00285             BCids.push_back( std::atoi( ids[i].c_str() ) );
00286     }
00287 
00288     if( metis_method.empty() )
00289     {
00290         metis_method = METIS_DEFAULT_METHOD;
00291     }
00292 
00293 #endif  // MOAB_HAVE_METIS
00294 
00295     if( !write_sets && !write_tags ) write_sets = true;
00296 
00297     if( -1 == power )
00298     {
00299         num_parts = opts.getReqArg< int >( "#parts" );
00300         power     = 1;
00301     }
00302     else if( power < 1 || power > 18 )
00303     {
00304         std::cerr << power << ": invalid power for multiple partitions. Expected value in [1,18]" << std::endl
00305                   << std::endl;
00306         opts.printHelp();
00307         return EXIT_FAILURE;
00308     }
00309     else
00310     {
00311         num_parts = 2;
00312     }
00313 
00314     if( part_dim < 0 || part_dim > 3 )
00315     {
00316         std::cerr << part_dim << " : invalid dimension" << std::endl << std::endl;
00317         opts.printHelp();
00318         return EXIT_FAILURE;
00319     }
00320 
00321     if( imbal_tol < 0.0 )
00322     {
00323         std::cerr << imbal_tol << ": invalid imbalance tolerance" << std::endl << std::endl;
00324         opts.printHelp();
00325         return EXIT_FAILURE;
00326     }
00327 
00328     bool load_msets = false;
00329     if( opts.getOpt( "set_l,l", &set_l ) )
00330     {
00331         load_msets = true;
00332         if( set_l.size() <= 0 )
00333         {
00334             std::cerr << " No material set id's to load" << std::endl << std::endl;
00335             opts.printHelp();
00336             return EXIT_FAILURE;
00337         }
00338     }
00339 
00340     if( num_parts <= 1 )
00341     {
00342         std::cerr << "** Please specify #parts = " << num_parts << " to be greater than 1." << std::endl << std::endl;
00343         opts.printHelp();
00344         return EXIT_FAILURE;
00345     }
00346 
00347     clock_t t = clock();
00348 
00349     const char* options = NULL;
00350     ErrorCode rval;
00351 #ifdef MOAB_HAVE_ZOLTAN
00352     if( part_geom_mesh_size > 0. ) options = "FACET_DISTANCE_TOLERANCE=0.1";
00353 #endif  // MOAB_HAVE_ZOLTAN
00354 
00355     std::cout << "Loading file " << input_file << "..." << std::endl;
00356     if( load_msets == false )
00357     {
00358         rval = mb.load_file( input_file.c_str(), 0, options );MB_CHK_SET_ERR( rval, "Failed to load input file: " + input_file );
00359     }
00360     else  // load the material set(s)
00361     {
00362         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 );
00363     }
00364     if( print_time )
00365         std::cout << "Read input file in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl;
00366 
00367     for( int dim = part_dim; dim >= 0; --dim )
00368     {
00369         int n;
00370         rval = mb.get_number_entities_by_dimension( 0, dim, n );
00371         if( MB_SUCCESS == rval && 0 != n )
00372         {
00373             part_dim = dim;
00374             break;
00375         }
00376     }
00377     if( part_dim < 0 )
00378     {
00379         std::cerr << input_file << " : file does not contain any mesh entities" << std::endl;
00380         return 2;
00381     }
00382 
00383     ReorderTool reorder_tool( &moab );
00384 
00385     for( int p = 0; p < power; p++ )
00386     {
00387         t = clock();
00388 #ifdef MOAB_HAVE_ZOLTAN
00389         if( moab_use_zoltan )
00390         {
00391             rval = zoltan_tool->partition_mesh_and_geometry(
00392                 part_geom_mesh_size, num_parts, zoltan_method.c_str(),
00393                 ( !parm_method.empty() ? parm_method.c_str() : oct_method.c_str() ), imbal_tol, part_dim, write_sets,
00394                 write_tags, obj_weight, edge_weight, part_surf, ghost, projection_type, recompute_box_rcb, print_time );MB_CHK_SET_ERR( rval, "Zoltan partitioner failed." );
00395         }
00396 #endif
00397 #ifdef MOAB_HAVE_METIS
00398         if( moab_use_metis )
00399         {
00400             rval = metis_tool->partition_mesh( num_parts, metis_method.c_str(), part_dim, write_sets, write_tags,
00401                                                partition_tagged_sets, partition_tagged_ents, aggregating_tag.c_str(),
00402                                                print_time );MB_CHK_SET_ERR( rval, "Metis partitioner failed." );
00403         }
00404 #endif
00405 
00406         if( print_time )
00407             std::cout << "Generated " << num_parts << " part partitioning in "
00408                       << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl;
00409 
00410         if( reorder && part_geom_mesh_size < 0. )
00411         {
00412             std::cout << "Reordering mesh for partition..." << std::endl;
00413 
00414             Tag tag, order;
00415             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" );
00416 
00417             t = clock();
00418             if( write_sets )
00419             {
00420                 Range sets;
00421                 mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, sets );
00422                 rval = reorder_tool.handle_order_from_sets_and_adj( sets, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." );
00423             }
00424             else
00425             {
00426                 rval = reorder_tool.handle_order_from_int_tag( tag, -1, order );MB_CHK_SET_ERR( rval, "Failed to calculate reordering." );
00427             }
00428 
00429             rval = reorder_tool.reorder_entities( order );MB_CHK_SET_ERR( rval, "Failed to perform reordering." );
00430 
00431             rval = mb.tag_delete( order );MB_CHK_SET_ERR( rval, "Failed to delete tag." );
00432             if( print_time )
00433                 std::cout << "Reordered mesh in " << ( clock() - t ) / (double)CLOCKS_PER_SEC << " seconds"
00434                           << std::endl;
00435         }
00436 
00437 #ifdef MOAB_HAVE_ZOLTAN
00438         if( incl_closure )
00439         {
00440             rval = zoltan_tool->include_closure();MB_CHK_SET_ERR( rval, "Closure inclusion failed." );
00441         }
00442 #endif
00443 
00444         std::ostringstream tmp_output_file;
00445 
00446         if( power > 1 )
00447         {
00448             // append num_parts to output filename
00449             std::string::size_type idx = output_file.find_last_of( "." );
00450             if( idx == std::string::npos )
00451             {
00452                 tmp_output_file << output_file << "_" << num_parts;
00453                 if( part_geom_mesh_size < 0. )
00454                     tmp_output_file << ".h5m";
00455                 else
00456                 {
00457                     std::cerr << "output file type is not specified." << std::endl;
00458                     return 1;
00459                 }
00460             }
00461             else
00462             {
00463                 tmp_output_file << output_file.substr( 0, idx ) << "_" << num_parts << output_file.substr( idx );
00464             }
00465         }
00466         else
00467             tmp_output_file << output_file;
00468 
00469         t = clock();
00470         std::cout << "Saving file to " << output_file << "..." << std::endl;
00471         if( part_geom_mesh_size < 0. )
00472         {
00473             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 );
00474         }
00475 #ifdef MOAB_HAVE_ZOLTAN
00476 #ifdef MOAB_HAVE_CGM
00477         else
00478         {
00479             std::string::size_type idx = output_file.find_last_of( "." );
00480             int c_size                 = output_file.length() - idx;
00481             const char* file_type      = NULL;
00482             if( output_file.compare( idx, c_size, ".occ" ) == 0 || output_file.compare( idx, c_size, ".OCC" ) == 0 )
00483                 file_type = "OCC";
00484             else if( output_file.compare( idx, c_size, ".sab" ) == 0 )
00485                 file_type = "ACIS_SAB";
00486             else if( output_file.compare( idx, c_size, ".sat" ) == 0 )
00487                 file_type = "ACIS_SAT";
00488             else
00489             {
00490                 std::cerr << "File type for " << output_file.c_str() << " not supported." << std::endl;
00491                 return 1;
00492             }
00493 
00494             int num_ents_exported = 0;
00495             DLIList< RefEntity* > ref_entity_list;
00496             CubitStatus status =
00497                 CubitCompat_export_solid_model( ref_entity_list, tmp_output_file.str().c_str(), file_type,
00498                                                 num_ents_exported, CubitString( __FILE__ ) );
00499             if( CUBIT_SUCCESS != status )
00500             {
00501                 std::cerr << "CGM couldn't export models." << std::endl;
00502                 return 1;
00503             }
00504         }
00505 #endif
00506 #endif
00507 
00508         if( print_time )
00509             std::cout << "Wrote \"" << tmp_output_file.str() << "\" in " << ( clock() - t ) / (double)CLOCKS_PER_SEC
00510                       << " seconds" << std::endl;
00511 
00512 #ifdef MOAB_HAVE_ZOLTAN
00513 
00514         if( moab_use_zoltan && moab_partition_slave && p == 0 )
00515         {
00516             t = clock();
00517             double master_radius, slave_radius;
00518             if( rescale_spherical_radius )
00519             {
00520                 EntityHandle rootset = 0;
00521                 Range masterverts;
00522                 rval = mb.get_entities_by_dimension( rootset, 0, masterverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" );
00523                 double points[6];
00524                 EntityHandle mfrontback[2] = { masterverts[0], masterverts[masterverts.size() - 1] };
00525                 rval                       = mb.get_coords( &mfrontback[0], 2, points );MB_CHK_ERR( rval );
00526                 const double mr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] );
00527                 const double mr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] );
00528                 master_radius    = 0.5 * ( mr1 + mr2 );
00529             }
00530             EntityHandle slaveset;
00531             rval = mb.create_meshset( moab::MESHSET_SET, slaveset );MB_CHK_SET_ERR( rval, "Can't create new set" );
00532             rval = mb.load_file( slave_file_name.c_str(), &slaveset, options );MB_CHK_SET_ERR( rval, "Can't load slave mesh" );
00533             if( rescale_spherical_radius )
00534             {
00535                 double points[6];
00536                 Range slaveverts;
00537                 rval = mb.get_entities_by_dimension( slaveset, 0, slaveverts );MB_CHK_SET_ERR( rval, "Can't create vertices on master set" );
00538                 EntityHandle sfrontback[2] = { slaveverts[0], slaveverts[slaveverts.size() - 1] };
00539                 rval                       = mb.get_coords( &sfrontback[0], 2, points );MB_CHK_ERR( rval );
00540                 const double sr1 = std::sqrt( points[0] * points[0] + points[1] * points[1] + points[2] * points[2] );
00541                 const double sr2 = std::sqrt( points[3] * points[3] + points[4] * points[4] + points[5] * points[5] );
00542                 slave_radius     = 0.5 * ( sr1 + sr2 );
00543                 // Let us rescale both master and slave meshes to a unit sphere
00544                 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, master_radius );MB_CHK_ERR( rval );
00545             }
00546 
00547             rval = zoltan_tool->partition_inferred_mesh( slaveset, num_parts, part_dim, write_sets, projection_type );MB_CHK_ERR( rval );
00548 
00549             if( rescale_spherical_radius )
00550             {
00551                 // rescale the slave mesh back to its original radius
00552                 rval = moab::IntxUtils::ScaleToRadius( &mb, slaveset, slave_radius );MB_CHK_ERR( rval );
00553             }
00554 
00555             if( print_time )
00556             {
00557                 std::cout << "Time taken to infer slave mesh partitions = " << ( clock() - t ) / (double)CLOCKS_PER_SEC
00558                           << " seconds" << std::endl;
00559             }
00560 
00561             size_t lastindex                 = slave_file_name.find_last_of( "." );
00562             std::string inferred_output_file = slave_file_name.substr( 0, lastindex ) + "_inferred" +
00563                                                slave_file_name.substr( lastindex, slave_file_name.size() );
00564 
00565             // Save the resulting mesh
00566             std::cout << "Saving inferred file to " << inferred_output_file << "..." << std::endl;
00567             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 );
00568         }
00569 #endif
00570 
00571         num_parts *= 2;
00572     }
00573 
00574 #ifdef MOAB_HAVE_ZOLTAN
00575     delete zoltan_tool;
00576 #endif
00577 #ifdef MOAB_HAVE_METIS
00578     delete metis_tool;
00579 #endif
00580 
00581 #ifdef MOAB_HAVE_MPI
00582     err = MPI_Finalize();
00583     assert( MPI_SUCCESS == err );
00584 #endif
00585     return 0;
00586 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines