MOAB: Mesh Oriented datABase
(version 5.4.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 ) 00130 { 00131 opts << ";PARTITION=" << part_opt; 00132 } 00133 else 00134 { 00135 char* endptr = 0; 00136 long n = strtol( part_opt.c_str() + p + 1, &endptr, 0 ); 00137 if( *endptr || p == part_opt.size() - 1 ) 00138 { 00139 std::cerr << "Warning: partition tag option contains an '=' followed " 00140 " by a non-integer value. Assuming tag name is " 00141 " \"" 00142 << part_opt << "\"" << std::endl; 00143 opts << ";PARTITION=" << part_opt; 00144 } 00145 else 00146 { 00147 opts << ";PARTITION=" << part_opt.substr( 0, p ); 00148 opts << ";PARTITION_VAL=" << n; 00149 } 00150 } 00151 00152 if( resolve_shared ) 00153 { 00154 opts << ";PARALLEL_RESOLVE_SHARED_ENTS"; 00155 } 00156 00157 if( debug_flag_str ) 00158 { 00159 char* endptr = 0; 00160 long n = strtol( debug_flag_str, &endptr, 0 ); 00161 if( *endptr || n < 0 || !*debug_flag_str ) usage( argv[0] ); 00162 opts << ";DEBUG_IO=" << n; 00163 } 00164 00165 Core moab; 00166 Interface& mb = moab; 00167 ParallelComm* pcomm = new ParallelComm( &mb, MPI_COMM_WORLD ); 00168 if( pcomm->rank() == 0 ) 00169 std::cout << "Loading file: \"" << input_file << "\" with options \"" << opts.str() << '"' << std::endl; 00170 opts << ";PARALLEL_COMM=" << pcomm->get_id(); 00171 00172 clock_t init_time = clock(); 00173 ErrorCode rval = mb.load_file( input_file, 0, opts.str().c_str() ); 00174 if( MB_SUCCESS != rval ) 00175 { 00176 std::cerr << input_file << " : file read failed (" << mb.get_error_string( rval ) << ")" << std::endl; 00177 return 1; 00178 } 00179 00180 clock_t t = clock(); 00181 double sec; 00182 if( t < init_time ) 00183 sec = 00184 ( std::numeric_limits< clock_t >::max() - init_time ) / (double)CLOCKS_PER_SEC + t / (double)CLOCKS_PER_SEC; 00185 else 00186 sec = ( t - init_time ) / (double)CLOCKS_PER_SEC; 00187 double allsec; 00188 MPI_Reduce( &sec, &allsec, 1, MPI_DOUBLE, MPI_MAX, 0, pcomm->comm() ); 00189 if( pcomm->rank() == 0 ) 00190 { 00191 std::cout << "Read completed in " << allsec << " seconds" << std::endl; 00192 } 00193 00194 int result = check_parallel_read( mb, pcomm, resolve_shared ); 00195 00196 if( MB_SUCCESS != pcomm->check_all_shared_handles( false ) ) ++result; 00197 00198 MPI_Finalize(); 00199 return result; 00200 } 00201 00202 int check_parallel_read( Interface& mb, ParallelComm* pcomm, bool /*shared_ents*/ ) 00203 { 00204 int error_count = 0; 00205 00206 const Range& parts = pcomm->partition_sets(); 00207 if( parts.empty() ) std::cout << "No parts for process " << pcomm->rank() << std::endl; 00208 00209 // get all entities from parts 00210 Range part_ents; 00211 for( Range::iterator i = parts.begin(); i != parts.end(); ++i ) 00212 mb.get_entities_by_handle( *i, part_ents ); 00213 00214 int dim = 3; 00215 if( part_ents.empty() ) 00216 std::cout << "No partitioned entities for process " << pcomm->rank() << std::endl; 00217 else 00218 { 00219 dim = CN::Dimension( mb.type_from_handle( part_ents.back() ) ); 00220 if( !part_ents.all_of_dimension( dim ) ) 00221 std::cout << "Partitioned ents of mixed dimension for process " << pcomm->rank() << std::endl; 00222 } 00223 00224 Range all_ents; 00225 mb.get_entities_by_dimension( 0, dim, all_ents ); 00226 if( !subtract( all_ents, part_ents ).empty() ) 00227 { 00228 std::cerr << "Process " << pcomm->rank() << " has entities of dimension " << dim 00229 << " that are not contained in any part" << std::endl; 00230 ++error_count; 00231 } 00232 00233 if( dim == 0 ) 00234 { 00235 std::cout << "Skipping further tests because mesh is vertex-partitioned" << std::endl; 00236 return error_count; 00237 } 00238 00239 Range part_verts; 00240 mb.get_connectivity( part_ents, part_verts ); 00241 Range all_verts; 00242 mb.get_entities_by_dimension( 0, 0, all_verts ); 00243 if( !subtract( all_verts, part_verts ).empty() ) 00244 { 00245 std::cerr << "Process " << pcomm->rank() << " has vertices " 00246 << " that are not contained in any partitioned element" << std::endl; 00247 ++error_count; 00248 } 00249 00250 // if (!shared_ents) { 00251 // std::cout << "Skipping further tests because shared entities were not resolved" << 00252 // std::endl; return error_count; 00253 //} 00254 00255 return error_count; 00256 }