MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 ) 00168 { 00169 o_ct++; 00170 } 00171 } 00172 MPI_Reduce( &o_ct, &o_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ); 00173 if( myID == 0 ) 00174 { 00175 std::cout << "There are " << o_tot << " vertices." << std::endl; 00176 std::cout << "------------------------------------------" << std::endl; 00177 } 00178 // Check the count of owned and not owned skin faces. 00179 // owned-not owned == total skin faces 00180 moab::Skinner skinner( mb ); 00181 o_ct = 0; 00182 no_ct = 0; 00183 o_tot = 0; 00184 no_tot = 0; 00185 skin.clear(); 00186 ents.clear(); 00187 mb->get_entities_by_dimension( 0, 3, ents ); 00188 skinner.find_skin( 0, ents, 2, skin ); 00189 for( moab::Range::iterator s_rit = skin.begin(); s_rit != skin.end(); ++s_rit ) 00190 { 00191 pc->get_owner( *s_rit, tmp ); 00192 if( tmp == myID ) 00193 { 00194 o_ct++; 00195 } 00196 else 00197 { 00198 no_ct++; 00199 } 00200 } 00201 MPI_Reduce( &o_ct, &o_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ); 00202 MPI_Reduce( &no_ct, &no_tot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ); 00203 if( myID == 0 ) 00204 { 00205 std::cout << "There are " << o_tot << " owned skin faces." << std::endl; 00206 std::cout << "There are " << no_tot << " not owned skin faces." << std::endl; 00207 std::cout << "The difference (Global Skin Faces) is " << ( o_tot - no_tot ) << "." << std::endl; 00208 std::cout << "------------------------------------------" << std::endl; 00209 } 00210 } 00211 }