MOAB: Mesh Oriented datABase  (version 5.2.1)
parmerge.cpp
Go to the documentation of this file.
00001 /* Parallel Merge Mesh Test
00002    Nathan Bertram
00003    5/31/11
00004 */
00005 
00006 #include "moab/ParallelMergeMesh.hpp"
00007 #include "moab/Core.hpp"
00008 #include "moab/Range.hpp"
00009 #include "moab_mpi.h"
00010 #include <iostream>
00011 #include <string>
00012 #include <cstdlib>
00013 #include "moab/ParallelMergeMesh.hpp"
00014 #include "moab/ParallelComm.hpp"
00015 #include "MBParallelConventions.h"
00016 #include <fstream>
00017 #include <sstream>
00018 #include "moab/Skinner.hpp"
00019 
00020 // Should we print out info on the merged mesh?
00021 #define PrintInfo false
00022 /*
00023     Parmerge
00024     Takes multiple mesh files and merges them into a single output file.
00025     This is a driver for ParallelMergeMesh
00026     Does not currently work if #procs > #meshfiles
00027 
00028     <inputfile> is text file containing each mesh file on a line
00029     i.e.
00030 
00031     /my/path/file1
00032     /my/path/file2
00033     ...
00034     /my/path/fileN
00035 
00036     <outputfile> file is a single file where the entire mesh is written to
00037     It must be of type ".h5m"
00038 
00039     <tolerance> is the merging tolerance
00040 
00041     Typical usage of:
00042     mpirun -n <#procs> parmerge <inputfile> <outputfile> <tolerance>
00043 */
00044 
00045 // Function to print out info for testing purposes
00046 void print_output( moab::ParallelComm* pc, moab::Core* mb, int numprocs, int myID, bool perform );
00047 
00048 int main( int argc, char* argv[] )
00049 {
00050     // Check argument count
00051     if( argc != 4 )
00052     {
00053         std::cerr << "Usage: " << argv[0] << " <inputfile> <outputfile> <tolerance>" << std::endl;
00054         return 1;
00055     }
00056     // Check the output file extension
00057     std::string outfile( argv[2] );
00058     if( outfile.compare( outfile.size() - 4, 4, ".h5m" ) != 0 )
00059     {
00060         std::cerr << "Invalid Parallel Output File" << std::endl;
00061         return 1;
00062     }
00063 
00064     // Read in tolerance
00065     double epsilon;
00066     if( !( std::istringstream( argv[3] ) >> epsilon ) )
00067     {
00068         std::cerr << "Unable to parse tolerance" << std::endl;
00069         return 1;
00070     }
00071 
00072     // Initialize MPI
00073     int numprocs, myID;
00074     MPI_Init( &argc, &argv );
00075     MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
00076     MPI_Comm_rank( MPI_COMM_WORLD, &myID );
00077 
00078     // Read in files from input files
00079     // Round robin distribution of reading meshes
00080     moab::Core* mb = new moab::Core();
00081     moab::ErrorCode rval;
00082     std::ifstream file( argv[1] );
00083     if( file.is_open() )
00084     {
00085         std::string line;
00086         int count = 0;
00087         // Read each line
00088         while( file.good() )
00089         {
00090             getline( file, line );
00091             if( myID == count && line != "" )
00092             {
00093                 // Read in the file
00094                 rval = mb->load_mesh( line.c_str() );
00095                 if( rval != moab::MB_SUCCESS )
00096                 {
00097                     std::cerr << "Error Opening Mesh File " << line << std::endl;
00098                     MPI_Abort( MPI_COMM_WORLD, 1 );
00099                     file.close();
00100                     return 1;
00101                 }
00102             }
00103             count = ( count + 1 ) % numprocs;
00104         }
00105         file.close();
00106     }
00107     else
00108     {
00109         std::cerr << "Error Opening Input File " << argv[1] << std::endl;
00110         MPI_Abort( MPI_COMM_WORLD, 1 );
00111         return 1;
00112     }
00113 
00114     // Get a pcomm object
00115     moab::ParallelComm* pc = new moab::ParallelComm( mb, MPI_COMM_WORLD );
00116 
00117     // Call the resolve parallel function
00118     moab::ParallelMergeMesh pm( pc, epsilon );
00119     rval = pm.merge();
00120     if( rval != moab::MB_SUCCESS )
00121     {
00122         std::cerr << "Merge Failed" << std::endl;
00123         MPI_Abort( MPI_COMM_WORLD, 1 );
00124         return 1;
00125     }
00126 
00127     print_output( pc, mb, myID, numprocs, PrintInfo );
00128 
00129     // Write out the file
00130     rval = mb->write_file( outfile.c_str(), 0, "PARALLEL=WRITE_PART" );
00131     if( rval != moab::MB_SUCCESS )
00132     {
00133         std::cerr << "Writing output file failed. Code:";
00134         // Temporary File error info.
00135         std::cerr << mb->get_error_string( rval ) << std::endl;
00136         std::string foo = "";
00137         mb->get_last_error( foo );
00138         std::cerr << "File Error: " << foo << std::endl;
00139         return 1;
00140     }
00141 
00142     // The barrier may be necessary to stop items from being deleted when needed
00143     // But probably not necessary
00144     MPI_Barrier( MPI_COMM_WORLD );
00145 
00146     delete pc;
00147     delete mb;
00148     MPI_Finalize();
00149 
00150     return 0;
00151 }
00152 
00153 // This function doesn't normally get called, but is here for debugging
00154 // and verifying that merge is working.
00155 void print_output( moab::ParallelComm* pc, moab::Core* mb, int myID, int /* numprocs */, bool perform )
00156 {
00157     moab::Range ents, skin;
00158     int o_ct = 0, no_ct = 0, tmp = 0, o_tot = 0, no_tot = 0;
00159     if( perform )
00160     {
00161         if( myID == 0 ) std::cout << "------------------------------------------" << std::endl;
00162         // Check the count of total vertices
00163         mb->get_entities_by_dimension( 0, 0, ents );
00164         for( moab::Range::iterator rit = ents.begin(); rit != ents.end(); ++rit )
00165         {
00166             pc->get_owner( *rit, tmp );
00167             if( tmp == myID ) { o_ct++; }
00168         }
00169         MPI_Reduce( &o_ct, &o_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
00170         if( myID == 0 )
00171         {
00172             std::cout << "There are " << o_tot << " vertices." << std::endl;
00173             std::cout << "------------------------------------------" << std::endl;
00174         }
00175         // Check the count of owned and not owned skin faces.
00176         // owned-not owned == total skin faces
00177         moab::Skinner skinner( mb );
00178         o_ct   = 0;
00179         no_ct  = 0;
00180         o_tot  = 0;
00181         no_tot = 0;
00182         skin.clear();
00183         ents.clear();
00184         mb->get_entities_by_dimension( 0, 3, ents );
00185         skinner.find_skin( 0, ents, 2, skin );
00186         for( moab::Range::iterator s_rit = skin.begin(); s_rit != skin.end(); ++s_rit )
00187         {
00188             pc->get_owner( *s_rit, tmp );
00189             if( tmp == myID ) { o_ct++; }
00190             else
00191             {
00192                 no_ct++;
00193             }
00194         }
00195         MPI_Reduce( &o_ct, &o_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
00196         MPI_Reduce( &no_ct, &no_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
00197         if( myID == 0 )
00198         {
00199             std::cout << "There are " << o_tot << " owned skin faces." << std::endl;
00200             std::cout << "There are " << no_tot << " not owned skin faces." << std::endl;
00201             std::cout << "The difference (Global Skin Faces) is " << ( o_tot - no_tot ) << "." << std::endl;
00202             std::cout << "------------------------------------------" << std::endl;
00203         }
00204     }
00205 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines