MOAB: Mesh Oriented datABase  (version 5.3.1)
partcheck.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines