MOAB: Mesh Oriented datABase  (version 5.5.0)
partcheck.cpp
Go to the documentation of this file.
1 #include "moab/Core.hpp"
2 #include "moab/Range.hpp"
3 #include "moab/ParallelComm.hpp"
4 #include "moab/Skinner.hpp"
5 #include "moab/CN.hpp"
6 
7 #include <iostream>
8 #include <sstream>
9 #include <limits>
10 #include <string>
11 #include <ctime>
12 
13 #include "moab_mpi.h"
14 
15 const char PARTTAG[] = "PARALLEL_PARTITION";
16 const char READ_DEL_OPT[] = "READ_DELETE";
17 const char BCAST_DEL_OPT[] = "BCAST_DELETE";
18 const char READ_PART_OPT[] = "READ_PART";
19 const char* const DEFAULT_MODE = READ_PART_OPT;
20 
21 const char USAGE[] = " [-v <n>] [-R] [-p <parttag>[=val]] [-D|-B|-P] <input_file>";
22 
23 static void usage( const char* argv0 )
24 {
25  std::cerr << "Usage: " << argv0 << USAGE << std::endl << " " << argv0 << " -h" << std::endl;
26  exit( 1 );
27 }
28 
29 static const char* defstr( const char* mode )
30 {
31  static const char s[] = " (default)";
32  int len = ( mode == DEFAULT_MODE ) ? 0 : sizeof( s ) - 1;
33  return s + len;
34 }
35 
36 static void help( const char* argv0 )
37 {
38  std::cout << "Usage: " << argv0 << USAGE << std::endl
39  << " -v : debug output level (DEBUG_IO option)" << std::endl
40  << " -R : do not resolve shared entities" << std::endl
41  << " -p : partition tag, with optional '=' value" << std::endl
42  << " (default = \"" << PARTTAG << "\")" << std::endl
43  << " -D : read mode as \"" << READ_DEL_OPT << "\"" << defstr( READ_DEL_OPT ) << std::endl
44  << " -B : read mode as \"" << BCAST_DEL_OPT << "\"" << defstr( READ_DEL_OPT ) << std::endl
45  << " -P : read mode as \"" << READ_PART_OPT << "\"" << defstr( READ_PART_OPT ) << std::endl;
46  exit( 0 );
47 }
48 
49 using namespace moab;
50 
51 int check_parallel_read( Interface& mb, ParallelComm* pcomm, bool shared_ents );
52 
53 int main( int argc, char* argv[] )
54 {
55  const char* read_mode_opt = DEFAULT_MODE;
56  const char* part_tag_opt = PARTTAG;
57  bool resolve_shared = true;
58  const char* input_file = 0;
59  const char* debug_flag_str = 0;
60  bool no_more_flags = false;
61 
62  MPI_Init( &argc, &argv );
63 
64  // process command line arguments
65 
66  for( int i = 1; i < argc; ++i )
67  {
68  if( !no_more_flags && argv[i][0] == '-' )
69  {
70  const char* opts = argv[i] + 1;
71  for( int j = 0; opts[j]; ++j )
72  {
73  switch( opts[j] )
74  {
75  case '-':
76  no_more_flags = true;
77  break;
78  case 'v':
79  if( ++i == argc ) usage( argv[0] );
80  debug_flag_str = argv[i];
81  break;
82  case 'R':
83  resolve_shared = false;
84  break;
85  case 'p':
86  if( ++i == argc ) usage( argv[0] );
87  part_tag_opt = argv[i];
88  break;
89  case 'D':
90  read_mode_opt = READ_DEL_OPT;
91  break;
92  case 'B':
93  read_mode_opt = BCAST_DEL_OPT;
94  break;
95  case 'P':
96  read_mode_opt = READ_PART_OPT;
97  break;
98  case 'h':
99  help( argv[0] );
100  break;
101  default:
102  usage( argv[0] );
103  }
104  }
105  }
106  else if( !input_file )
107  {
108  input_file = argv[i];
109  }
110  else
111  {
112  usage( argv[0] );
113  }
114  }
115 
116  if( !input_file )
117  {
118  std::cerr << argv[0] << ": no input file specified" << std::endl;
119  usage( argv[0] );
120  }
121 
122  // build options string
123 
124  std::ostringstream opts;
125  opts << "PARALLEL=" << read_mode_opt;
126 
127  std::string part_opt( part_tag_opt );
128  size_t p = part_opt.find_last_of( '=' );
129  if( p == std::string::npos )
130  {
131  opts << ";PARTITION=" << part_opt;
132  }
133  else
134  {
135  char* endptr = 0;
136  long n = strtol( part_opt.c_str() + p + 1, &endptr, 0 );
137  if( *endptr || p == part_opt.size() - 1 )
138  {
139  std::cerr << "Warning: partition tag option contains an '=' followed "
140  " by a non-integer value. Assuming tag name is "
141  " \""
142  << part_opt << "\"" << std::endl;
143  opts << ";PARTITION=" << part_opt;
144  }
145  else
146  {
147  opts << ";PARTITION=" << part_opt.substr( 0, p );
148  opts << ";PARTITION_VAL=" << n;
149  }
150  }
151 
152  if( resolve_shared )
153  {
154  opts << ";PARALLEL_RESOLVE_SHARED_ENTS";
155  }
156 
157  if( debug_flag_str )
158  {
159  char* endptr = 0;
160  long n = strtol( debug_flag_str, &endptr, 0 );
161  if( *endptr || n < 0 || !*debug_flag_str ) usage( argv[0] );
162  opts << ";DEBUG_IO=" << n;
163  }
164 
165  Core moab;
166  Interface& mb = moab;
167  ParallelComm* pcomm = new ParallelComm( &mb, MPI_COMM_WORLD );
168  if( pcomm->rank() == 0 )
169  std::cout << "Loading file: \"" << input_file << "\" with options \"" << opts.str() << '"' << std::endl;
170  opts << ";PARALLEL_COMM=" << pcomm->get_id();
171 
172  clock_t init_time = clock();
173  ErrorCode rval = mb.load_file( input_file, 0, opts.str().c_str() );
174  if( MB_SUCCESS != rval )
175  {
176  std::cerr << input_file << " : file read failed (" << mb.get_error_string( rval ) << ")" << std::endl;
177  return 1;
178  }
179 
180  clock_t t = clock();
181  double sec;
182  if( t < init_time )
183  sec =
184  ( std::numeric_limits< clock_t >::max() - init_time ) / (double)CLOCKS_PER_SEC + t / (double)CLOCKS_PER_SEC;
185  else
186  sec = ( t - init_time ) / (double)CLOCKS_PER_SEC;
187  double allsec;
188  MPI_Reduce( &sec, &allsec, 1, MPI_DOUBLE, MPI_MAX, 0, pcomm->comm() );
189  if( pcomm->rank() == 0 )
190  {
191  std::cout << "Read completed in " << allsec << " seconds" << std::endl;
192  }
193 
194  int result = check_parallel_read( mb, pcomm, resolve_shared );
195 
196  if( MB_SUCCESS != pcomm->check_all_shared_handles( false ) ) ++result;
197 
198  MPI_Finalize();
199  return result;
200 }
201 
202 int check_parallel_read( Interface& mb, ParallelComm* pcomm, bool /*shared_ents*/ )
203 {
204  int error_count = 0;
205 
206  const Range& parts = pcomm->partition_sets();
207  if( parts.empty() ) std::cout << "No parts for process " << pcomm->rank() << std::endl;
208 
209  // get all entities from parts
210  Range part_ents;
211  for( Range::iterator i = parts.begin(); i != parts.end(); ++i )
212  mb.get_entities_by_handle( *i, part_ents );
213 
214  int dim = 3;
215  if( part_ents.empty() )
216  std::cout << "No partitioned entities for process " << pcomm->rank() << std::endl;
217  else
218  {
219  dim = CN::Dimension( mb.type_from_handle( part_ents.back() ) );
220  if( !part_ents.all_of_dimension( dim ) )
221  std::cout << "Partitioned ents of mixed dimension for process " << pcomm->rank() << std::endl;
222  }
223 
224  Range all_ents;
225  mb.get_entities_by_dimension( 0, dim, all_ents );
226  if( !subtract( all_ents, part_ents ).empty() )
227  {
228  std::cerr << "Process " << pcomm->rank() << " has entities of dimension " << dim
229  << " that are not contained in any part" << std::endl;
230  ++error_count;
231  }
232 
233  if( dim == 0 )
234  {
235  std::cout << "Skipping further tests because mesh is vertex-partitioned" << std::endl;
236  return error_count;
237  }
238 
239  Range part_verts;
240  mb.get_connectivity( part_ents, part_verts );
241  Range all_verts;
242  mb.get_entities_by_dimension( 0, 0, all_verts );
243  if( !subtract( all_verts, part_verts ).empty() )
244  {
245  std::cerr << "Process " << pcomm->rank() << " has vertices "
246  << " that are not contained in any partitioned element" << std::endl;
247  ++error_count;
248  }
249 
250  // if (!shared_ents) {
251  // std::cout << "Skipping further tests because shared entities were not resolved" <<
252  // std::endl; return error_count;
253  //}
254 
255  return error_count;
256 }