MOAB: Mesh Oriented datABase
(version 5.3.1)
|
00001 #include "moab/Core.hpp" 00002 #include "moab/Range.hpp" 00003 #include "moab/ParallelComm.hpp" 00004 #include "moab/Skinner.hpp" 00005 #include "moab/CN.hpp" 00006 00007 #include <iostream> 00008 #include <sstream> 00009 #include <limits> 00010 #include <string> 00011 #include <ctime> 00012 00013 #include "moab_mpi.h" 00014 00015 const char PARTTAG[] = "PARALLEL_PARTITION"; 00016 const char READ_DEL_OPT[] = "READ_DELETE"; 00017 const char BCAST_DEL_OPT[] = "BCAST_DELETE"; 00018 const char READ_PART_OPT[] = "READ_PART"; 00019 const char* const DEFAULT_MODE = READ_PART_OPT; 00020 00021 const char USAGE[] = " [-v <n>] [-R] [-p <parttag>[=val]] [-D|-B|-P] <input_file>"; 00022 00023 static void usage( const char* argv0 ) 00024 { 00025 std::cerr << "Usage: " << argv0 << USAGE << std::endl << " " << argv0 << " -h" << std::endl; 00026 exit( 1 ); 00027 } 00028 00029 static const char* defstr( const char* mode ) 00030 { 00031 static const char s[] = " (default)"; 00032 int len = ( mode == DEFAULT_MODE ) ? 0 : sizeof( s ) - 1; 00033 return s + len; 00034 } 00035 00036 static void help( const char* argv0 ) 00037 { 00038 std::cout << "Usage: " << argv0 << USAGE << std::endl 00039 << " -v : debug output level (DEBUG_IO option)" << std::endl 00040 << " -R : do not resolve shared entities" << std::endl 00041 << " -p : partition tag, with optional '=' value" << std::endl 00042 << " (default = \"" << PARTTAG << "\")" << std::endl 00043 << " -D : read mode as \"" << READ_DEL_OPT << "\"" << defstr( READ_DEL_OPT ) << std::endl 00044 << " -B : read mode as \"" << BCAST_DEL_OPT << "\"" << defstr( READ_DEL_OPT ) << std::endl 00045 << " -P : read mode as \"" << READ_PART_OPT << "\"" << defstr( READ_PART_OPT ) << std::endl; 00046 exit( 0 ); 00047 } 00048 00049 using namespace moab; 00050 00051 int check_parallel_read( Interface& mb, ParallelComm* pcomm, bool shared_ents ); 00052 00053 int main( int argc, char* argv[] ) 00054 { 00055 const char* read_mode_opt = DEFAULT_MODE; 00056 const char* part_tag_opt = PARTTAG; 00057 bool resolve_shared = true; 00058 const char* input_file = 0; 00059 const char* debug_flag_str = 0; 00060 bool no_more_flags = false; 00061 00062 MPI_Init( &argc, &argv ); 00063 00064 // process command line arguments 00065 00066 for( int i = 1; i < argc; ++i ) 00067 { 00068 if( !no_more_flags && argv[i][0] == '-' ) 00069 { 00070 const char* opts = argv[i] + 1; 00071 for( int j = 0; opts[j]; ++j ) 00072 { 00073 switch( opts[j] ) 00074 { 00075 case '-': 00076 no_more_flags = true; 00077 break; 00078 case 'v': 00079 if( ++i == argc ) usage( argv[0] ); 00080 debug_flag_str = argv[i]; 00081 break; 00082 case 'R': 00083 resolve_shared = false; 00084 break; 00085 case 'p': 00086 if( ++i == argc ) usage( argv[0] ); 00087 part_tag_opt = argv[i]; 00088 break; 00089 case 'D': 00090 read_mode_opt = READ_DEL_OPT; 00091 break; 00092 case 'B': 00093 read_mode_opt = BCAST_DEL_OPT; 00094 break; 00095 case 'P': 00096 read_mode_opt = READ_PART_OPT; 00097 break; 00098 case 'h': 00099 help( argv[0] ); 00100 break; 00101 default: 00102 usage( argv[0] ); 00103 } 00104 } 00105 } 00106 else if( !input_file ) 00107 { 00108 input_file = argv[i]; 00109 } 00110 else 00111 { 00112 usage( argv[0] ); 00113 } 00114 } 00115 00116 if( !input_file ) 00117 { 00118 std::cerr << argv[0] << ": no input file specified" << std::endl; 00119 usage( argv[0] ); 00120 } 00121 00122 // build options string 00123 00124 std::ostringstream opts; 00125 opts << "PARALLEL=" << read_mode_opt; 00126 00127 std::string part_opt( part_tag_opt ); 00128 size_t p = part_opt.find_last_of( '=' ); 00129 if( p == std::string::npos ) { opts << ";PARTITION=" << part_opt; } 00130 else 00131 { 00132 char* endptr = 0; 00133 long n = strtol( part_opt.c_str() + p + 1, &endptr, 0 ); 00134 if( *endptr || p == part_opt.size() - 1 ) 00135 { 00136 std::cerr << "Warning: partition tag option contains an '=' followed " 00137 " by a non-integer value. Assuming tag name is " 00138 " \"" 00139 << part_opt << "\"" << std::endl; 00140 opts << ";PARTITION=" << part_opt; 00141 } 00142 else 00143 { 00144 opts << ";PARTITION=" << part_opt.substr( 0, p ); 00145 opts << ";PARTITION_VAL=" << n; 00146 } 00147 } 00148 00149 if( resolve_shared ) { opts << ";PARALLEL_RESOLVE_SHARED_ENTS"; } 00150 00151 if( debug_flag_str ) 00152 { 00153 char* endptr = 0; 00154 long n = strtol( debug_flag_str, &endptr, 0 ); 00155 if( *endptr || n < 0 || !*debug_flag_str ) usage( argv[0] ); 00156 opts << ";DEBUG_IO=" << n; 00157 } 00158 00159 Core moab; 00160 Interface& mb = moab; 00161 ParallelComm* pcomm = new ParallelComm( &mb, MPI_COMM_WORLD ); 00162 if( pcomm->rank() == 0 ) 00163 std::cout << "Loading file: \"" << input_file << "\" with options \"" << opts.str() << '"' << std::endl; 00164 opts << ";PARALLEL_COMM=" << pcomm->get_id(); 00165 00166 clock_t init_time = clock(); 00167 ErrorCode rval = mb.load_file( input_file, 0, opts.str().c_str() ); 00168 if( MB_SUCCESS != rval ) 00169 { 00170 std::cerr << input_file << " : file read failed (" << mb.get_error_string( rval ) << ")" << std::endl; 00171 return 1; 00172 } 00173 00174 clock_t t = clock(); 00175 double sec; 00176 if( t < init_time ) 00177 sec = 00178 ( std::numeric_limits< clock_t >::max() - init_time ) / (double)CLOCKS_PER_SEC + t / (double)CLOCKS_PER_SEC; 00179 else 00180 sec = ( t - init_time ) / (double)CLOCKS_PER_SEC; 00181 double allsec; 00182 MPI_Reduce( &sec, &allsec, 1, MPI_DOUBLE, MPI_MAX, 0, pcomm->comm() ); 00183 if( pcomm->rank() == 0 ) { std::cout << "Read completed in " << allsec << " seconds" << std::endl; } 00184 00185 int result = check_parallel_read( mb, pcomm, resolve_shared ); 00186 00187 if( MB_SUCCESS != pcomm->check_all_shared_handles( false ) ) ++result; 00188 00189 MPI_Finalize(); 00190 return result; 00191 } 00192 00193 int check_parallel_read( Interface& mb, ParallelComm* pcomm, bool /*shared_ents*/ ) 00194 { 00195 int error_count = 0; 00196 00197 const Range& parts = pcomm->partition_sets(); 00198 if( parts.empty() ) std::cout << "No parts for process " << pcomm->rank() << std::endl; 00199 00200 // get all entities from parts 00201 Range part_ents; 00202 for( Range::iterator i = parts.begin(); i != parts.end(); ++i ) 00203 mb.get_entities_by_handle( *i, part_ents ); 00204 00205 int dim = 3; 00206 if( part_ents.empty() ) 00207 std::cout << "No partitioned entities for process " << pcomm->rank() << std::endl; 00208 else 00209 { 00210 dim = CN::Dimension( mb.type_from_handle( part_ents.back() ) ); 00211 if( !part_ents.all_of_dimension( dim ) ) 00212 std::cout << "Partitioned ents of mixed dimension for process " << pcomm->rank() << std::endl; 00213 } 00214 00215 Range all_ents; 00216 mb.get_entities_by_dimension( 0, dim, all_ents ); 00217 if( !subtract( all_ents, part_ents ).empty() ) 00218 { 00219 std::cerr << "Process " << pcomm->rank() << " has entities of dimension " << dim 00220 << " that are not contained in any part" << std::endl; 00221 ++error_count; 00222 } 00223 00224 if( dim == 0 ) 00225 { 00226 std::cout << "Skipping further tests because mesh is vertex-partitioned" << std::endl; 00227 return error_count; 00228 } 00229 00230 Range part_verts; 00231 mb.get_connectivity( part_ents, part_verts ); 00232 Range all_verts; 00233 mb.get_entities_by_dimension( 0, 0, all_verts ); 00234 if( !subtract( all_verts, part_verts ).empty() ) 00235 { 00236 std::cerr << "Process " << pcomm->rank() << " has vertices " 00237 << " that are not contained in any partitioned element" << std::endl; 00238 ++error_count; 00239 } 00240 00241 // if (!shared_ents) { 00242 // std::cout << "Skipping further tests because shared entities were not resolved" << 00243 // std::endl; return error_count; 00244 //} 00245 00246 return error_count; 00247 }