1 #include <iostream>
2 #include <stdlib.h>
3 #include <vector>
4 #include <set>
5 #include <string>
6 #include <stdio.h>
7 #include <iomanip>
8 #include "moab/MOABConfig.h"
9 #ifndef WIN32
10 #  include <sys/times.h>
11 #  include <limits.h>
12 #  include <unistd.h>
13 #endif
14 #include <time.h>
15 #ifdef MOAB_HAVE_MPI
16 #  include "moab_mpi.h"
17 #endif
18 #if !defined(_MSC_VER) && !defined(__MINGW32__)
19 #  include <termios.h>
20 #  include <sys/ioctl.h>
21 #endif
22 #include <math.h>
23 #include <assert.h>
24 #include <float.h>
25 
26 #include "moab/Core.hpp"
27 #include "moab/Range.hpp"
28 #include "MBTagConventions.hpp"
29 #include "moab/Interface.hpp"
30 #include "moab/ReaderWriterSet.hpp"
31 
32 /* Exit values */
33 #define USAGE_ERROR 1
34 #define READ_ERROR 2
35 #define WRITE_ERROR 3
36 #define OTHER_ERROR 4
37 #define ENT_NOT_FOUND 5
38 
39 using namespace moab;
40 
41 #include "measure.hpp"
42 
print_usage(const char * name,std::ostream & stream)43 static void print_usage( const char* name, std::ostream& stream )
44 {
45   stream << "Usage: " << name
46          << " <options> <input_file> [<input_file2> ...]" << std::endl
47          << "Options: " << std::endl
48          << "\t-f             - List available file formats and exit." << std::endl
49          << "\t-g             - print counts by geometric owner" << std::endl
50          << "\t-h             - Print this help text and exit." << std::endl
51          << "\t-l             - Print counts of mesh" << std::endl
52          << "\t-ll            - Verbose listing of every entity" << std::endl
53          << "\t-m             - Print counts per block/boundary" << std::endl
54          << "\t-O option      - Specify read option." << std::endl
55 #ifdef MOAB_HAVE_MPI
56          << "\t-p[0|1|2]      - Read in parallel[0], optionally also doing resolve_shared_ents (1) and exchange_ghosts (2)" << std::endl
57 #endif
58          << "\t-t             - Print counts by tag" << std::endl
59          << "\t-T             - Time read of files." << std::endl
60          << "\t--             - treat all subsequent options as file names" << std::endl
61          << "\t                 (allows file names beginning with '-')" << std::endl
62     ;
63 }
64 
65 Core mb;
66 
67 
68 struct stat_set
69 {
70   double sum;
71   double sqr;
72   double min;
73   double max;
74   long count;
75 
stat_setstat_set76   inline stat_set() : sum(0), sqr(0), min(HUGE_VAL), max(0), count (0) {}
77 
addstat_set78   inline void add( double val )
79   {
80     if (val < min)
81       min = val;
82     if (val > max)
83       max = val;
84     sum += val;
85     sqr += val*val;
86     ++count;
87   }
88 
addstat_set89   inline void add( const stat_set& stats )
90   {
91     if (stats.min < min)
92       min = stats.min;
93     if (stats.max > max)
94       max = stats.max;
95     sum += stats.sum;
96     sqr += stats.sqr;
97     count += stats.count;
98   }
99 
clearstat_set100   inline void clear()
101   {
102     sum = sqr = 0.0;
103     max = count = 0;
104     min = HUGE_VAL;
105   }
106 };
107 
108 struct set_stats {
109   stat_set stats[MBMAXTYPE];
110   stat_set edge_uses;
111   size_t nodes;
112 
addset_stats113   void add( const set_stats& other )
114   {
115     for (int i = 0; i < MBMAXTYPE; ++i)
116       stats[i].add( other.stats[i] );
117     edge_uses.add( other.edge_uses );
118   }
119 
clearset_stats120   void clear()
121   {
122     for (int i = 0; i < MBMAXTYPE; ++i)
123       stats[i].clear();
124     edge_uses.clear();
125   }
126 
127 };
128 
129 
gather_set_stats(EntityHandle set,set_stats & stats)130 static ErrorCode gather_set_stats( EntityHandle set, set_stats& stats )
131 {
132   int count;
133   ErrorCode rval = mb.get_number_entities_by_type( set, MBVERTEX, count );
134   if (MB_SUCCESS != rval) return rval;
135   stats.nodes = count;
136 
137   int edge_vtx_idx[2];
138   std::vector<EntityHandle> conn;
139   std::vector<double> coords;
140   for (EntityType type = MBEDGE; type < MBENTITYSET; ++type)
141   {
142     int num_edges = CN::NumSubEntities( type, 1 );
143 
144     Range range;
145     rval = mb.get_entities_by_type( set, type, range, true );
146     if (MB_SUCCESS != rval) return rval;
147     for (Range::iterator i = range.begin(); i != range.end(); ++i)
148     {
149       rval = mb.get_connectivity( &*i, 1, conn, true );
150       if (MB_SUCCESS != rval) return rval;
151       if (type == MBPOLYHEDRON) {
152         std::vector<EntityHandle> dum_conn(conn);
153         conn.clear();
154         rval = mb.get_adjacencies(&dum_conn[0], dum_conn.size(), 0, false, conn, Interface::UNION);
155         if (MB_SUCCESS != rval) return rval;
156       }
157       coords.resize( 3*conn.size() );
158       rval = mb.get_coords( &conn[0], conn.size(), &coords[0] );
159       if (MB_SUCCESS != rval) return rval;
160       stats.stats[type].add( measure( type, conn.size(), &coords[0] ) );
161 
162       if (type != MBEDGE)
163       {
164         if (type == MBPOLYGON)
165           num_edges = conn.size();
166 
167         for (int e = 0; e < num_edges; ++e)
168         {
169           if (type == MBPOLYGON) {
170             edge_vtx_idx[0] = e;
171             edge_vtx_idx[1] = (e+1)%num_edges;
172           }
173           else
174             CN::SubEntityVertexIndices( type, 1, e, edge_vtx_idx );
175           stats.edge_uses.add( edge_length( &coords[3*edge_vtx_idx[0]],
176                                             &coords[3*edge_vtx_idx[1]] ) );
177         }
178       }
179     }
180   }
181   return MB_SUCCESS;
182 }
183 
184 struct TagCounts {
TagCountsTagCounts185   TagCounts(std::string n) : name(n)
186     { std::fill(counts, counts+MBMAXTYPE, 0); }
187   std::string name;
188   int counts[MBMAXTYPE];
189 };
190 
gather_tag_counts(EntityHandle set,std::vector<TagCounts> & counts)191 static ErrorCode gather_tag_counts( EntityHandle set,
192                                     std::vector<TagCounts>& counts )
193 {
194   std::vector<Tag> tags;
195   mb.tag_get_tags( tags );
196   for (size_t i = 0; i < tags.size(); ++i) {
197     std::string name;
198     ErrorCode rval = mb.tag_get_name( tags[i], name );
199     if (MB_SUCCESS != rval || name.empty())
200       continue;
201 
202     counts.push_back( name );
203     for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
204       mb.get_number_entities_by_type_and_tag( set, t, &tags[i], 0, 1, counts.back().counts[t] );
205   }
206 
207   return MB_SUCCESS;
208 }
209 
add_tag_counts(std::vector<TagCounts> & counts,const std::vector<TagCounts> & add)210 void add_tag_counts( std::vector<TagCounts>& counts,
211                      const std::vector<TagCounts>& add )
212 {
213   for (size_t i = 0; i < add.size(); ++i) {
214     size_t j;
215     for (j = 0; j < counts.size(); ++j)
216       if (add[i].name == counts[j].name)
217         break;
218     if (j == counts.size()) {
219       counts.push_back( add[i] );
220       continue;
221     }
222     for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
223       counts[j].counts[t] += add[i].counts[t];
224   }
225 }
226 
dashes(unsigned count)227 static const char* dashes( unsigned count )
228 {
229   static std::vector<char> dashes;
230   dashes.clear();
231   dashes.resize( count + 1, '-' );
232   dashes[count] = '\0';
233   return &dashes[0];
234 }
235 
print_tag_counts(const std::vector<TagCounts> & counts)236 static void print_tag_counts( const std::vector<TagCounts>& counts )
237 {
238   if (counts.empty()) {
239     printf( "<No tags>\n");
240     return;
241   }
242 
243   int widths[MBMAXTYPE] = { 0 };
244   int name_width = 0;
245   for (size_t i = 0; i < counts.size(); ++i) {
246     if (counts[i].name.length() > (unsigned)name_width)
247       name_width = counts[i].name.length();
248     for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
249       if (counts[i].counts[t] != 0)
250         widths[t] = std::max(8,(int)strlen(CN::EntityTypeName(t)));
251   }
252 
253   if (0 == std::min_element(widths, widths+MBMAXTYPE)) {
254     printf( "<No Tagged Entities>\n");
255     return;
256   }
257 
258     // Print header line
259   const char* name_title = "Tag Name";
260   if ((unsigned)name_width < strlen(name_title))
261     name_width = strlen(name_title);
262   printf( "%*s", name_width, name_title );
263   for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
264     if (widths[t])
265       printf( " %*s", widths[t], CN::EntityTypeName(t) );
266   printf("\n%s", dashes(name_width));
267   for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
268     if (widths[t])
269       printf( " %s", dashes(widths[t]) );
270   printf("\n");
271 
272     // print data
273   for (size_t i = 0; i < counts.size(); ++i) {
274     printf( "%*s", name_width, counts[i].name.c_str() );
275     for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t)
276       if (widths[t])
277         printf( " %*d", widths[t], counts[i].counts[t] );
278     printf("\n");
279   }
280 }
281 
print_stats(set_stats & stats)282 static void print_stats( set_stats& stats )
283 {
284   const char* edge_use_name = "1D Side";
285   const char* vertex_name = "Vertex";
286 
287   bool have_some = stats.edge_uses.count > 0 || stats.nodes > 0;
288   for (int i = 0; i < MBMAXTYPE; ++i)
289     if (stats.stats[i].count > 0)
290       have_some = true;
291 
292   if (!have_some)
293   {
294     std::cout << "NO MESH" << std::endl;
295     return;
296   }
297 
298     // get field widths
299   unsigned type_width = std::max( strlen(vertex_name), strlen( edge_use_name ) );
300   unsigned count_width = 5;
301   unsigned total_width = 5;
302   unsigned total_prec = 2;
303   unsigned precision = 5;
304   int total_log = -10000;
305 
306   unsigned node_count_width = (unsigned)(ceil(log10((double)stats.nodes))) + 1;
307   if (count_width < node_count_width)
308     count_width = node_count_width;
309 
310   for (EntityType i = MBEDGE; i < MBMAXTYPE; ++i)
311   {
312     stat_set& s = stats.stats[i];
313 
314     if (s.count == 0)
315       continue;
316 
317     unsigned len = strlen(CN::EntityTypeName(i));
318     if (len > type_width)
319       type_width = len;
320 
321     unsigned cw = (unsigned)(ceil(log10((double)s.count))) + 1;
322     if (cw > count_width)
323       count_width = cw;
324 
325     int tl = (unsigned)(ceil(log10(fabs(s.sum)))) + 1;
326     if (tl > total_log)
327       total_log = tl;
328   }
329 
330   if (total_log > (int)total_width || total_log == -10000)
331   {
332     total_width = 8;
333     total_prec = 2;
334   }
335   else if (total_log <= -(int)total_width)
336   {
337     total_width = -total_log + 5;
338     total_prec = 2;
339   }
340   else if (total_log < 1)
341   {
342     total_width = -total_log + 4;
343     total_prec = -total_log + 1;
344   }
345   else
346   {
347     total_width += 2;
348   }
349 
350 
351   // get terminal width
352   unsigned term_width = 80;
353 #if !defined(_MSC_VER) && !defined(__MINGW32__)
354   struct winsize size;
355   if ( ioctl( fileno(stdout), TIOCGWINSZ, (char*)&size ) == 0 )
356     term_width = size.ws_col;
357   if (!term_width) term_width = 80;
358 #endif
359   assert(term_width > 7 + type_width + count_width + total_width);
360 
361   term_width -= 7; // spaces
362   term_width -= type_width;
363   term_width -= count_width;
364   term_width -= total_width;
365   unsigned val_width = term_width / 5;
366   if (val_width < 8)
367     val_width = 8;
368 
369   printf( "%*s %*s %*s %*s %*s %*s %*s %*s\n",
370           type_width, "type",
371           count_width, "count",
372           total_width, "total",
373           val_width, "minimum",
374           val_width, "average",
375           val_width, "rms",
376           val_width, "maximum",
377           val_width, "std.dev." );
378 
379   printf( "%*s ", type_width, dashes(type_width) );
380   printf( "%*s ", count_width, dashes(count_width) );
381   printf( "%*s ", total_width, dashes(total_width) );
382   printf( "%*s ", val_width, dashes(val_width) );
383   printf( "%*s ", val_width, dashes(val_width) );
384   printf( "%*s ", val_width, dashes(val_width) );
385   printf( "%*s ", val_width, dashes(val_width) );
386   printf( "%*s\n", val_width, dashes(val_width) );
387 
388   for (EntityType i = MBEDGE; i <= MBMAXTYPE; ++i)
389   {
390     stat_set& s = (i == MBMAXTYPE) ? stats.edge_uses : stats.stats[i];
391 
392     if (s.count == 0)
393       continue;
394 
395     double tmp_dbl = s.sqr / s.count - s.sum*s.sum / (double)s.count / (double)s.count;
396     if (tmp_dbl < 0.0) {
397       if (tmp_dbl < -100.0*DBL_EPSILON)
398         std::cout << "WARNING: stat values dubious, s^2 - sig_s = " << tmp_dbl << std::endl;
399       tmp_dbl = 0.0;
400     }
401 
402     printf( "%*s %*ld %*.*g %*.*g %*.*g %*.*g %*.*g %*.*g\n",
403             type_width, i == MBMAXTYPE ? edge_use_name : CN::EntityTypeName(i),
404             count_width, s.count,
405             total_width, total_prec, s.sum,
406             val_width, precision, s.min,
407             val_width, precision, s.sum / s.count,
408             val_width, precision, sqrt( s.sqr / s.count ),
409             val_width, precision, s.max,
410             val_width, precision,
411             sqrt(tmp_dbl)
412           );
413   }
414   printf( "%*s %*lu\n", type_width, vertex_name, count_width, (unsigned long)stats.nodes );
415 
416   puts("");
417 }
418 
parse_id_list(const char * string,std::set<int> & results)419 bool parse_id_list( const char* string, std::set<int>& results )
420 {
421   bool okay = true;
422   char* mystr = strdup( string );
423   for (const char* ptr = strtok(mystr, ","); ptr; ptr = strtok(0,","))
424   {
425     char* endptr;
426     long val = strtol( ptr, &endptr, 0 );
427     if (endptr == ptr || val <= 0) {
428       std::cerr << "Not a valid id: " << ptr << std::endl;
429       okay = false;
430       break;
431     }
432 
433     long val2 = val;
434     if (*endptr == '-') {
435       const char* sptr = endptr+1;
436       val2 = strtol( sptr, &endptr, 0 );
437       if (endptr == sptr || val2 <= 0) {
438         std::cerr << "Not a valid id: " << sptr << std::endl;
439         okay = false;
440         break;
441       }
442       if (val2 < val) {
443         std::cerr << "Invalid id range: " << ptr << std::endl;
444         okay = false;
445         break;
446       }
447     }
448 
449     if (*endptr) {
450       std::cerr << "Unexpected character: " << *endptr << std::endl;
451       okay = false;
452       break;
453     }
454 
455     for (; val <= val2; ++val)
456       if (!results.insert( (int)val ).second)
457         std::cerr << "Warning: duplicate Id: " << val << std::endl;
458 
459   }
460 
461   free( mystr );
462   return okay;
463 }
464 
make_opts_string(std::vector<std::string> options,std::string & opts)465 bool make_opts_string( std::vector<std::string> options, std::string& opts )
466 {
467   opts.clear();
468   if (options.empty())
469     return true;
470 
471     // choose a separator character
472   std::vector<std::string>::const_iterator i;
473   char separator = '\0';
474   const char* alt_separators = ";+,:\t\n";
475   for (const char* sep_ptr = alt_separators; *sep_ptr; ++sep_ptr) {
476     bool seen = false;
477     for (i = options.begin(); i != options.end(); ++i)
478       if (i->find( *sep_ptr, 0 ) != std::string::npos) {
479         seen = true;
480         break;
481       }
482     if (!seen) {
483       separator = *sep_ptr;
484       break;
485     }
486   }
487   if (!separator) {
488     std::cerr << "Error: cannot find separator character for options string" << std::endl;
489     return false;
490   }
491   if (separator != ';') {
492     opts = ";";
493     opts += separator;
494   }
495 
496     // concatenate options
497   i = options.begin();
498   opts += *i;
499   for (++i; i != options.end(); ++i) {
500     opts += separator;
501     opts += *i;
502   }
503 
504   return true;
505 }
506 
507 
list_formats(Interface * gMB)508 void list_formats( Interface* gMB )
509 {
510   const char iface_name[] = "ReaderWriterSet";
511   ErrorCode err;
512   ReaderWriterSet* set = 0;
513   ReaderWriterSet::iterator i;
514   std::ostream& str = std::cout;
515 
516     // get ReaderWriterSet
517   err = gMB->query_interface( set );
518   if (err != MB_SUCCESS || !set) {
519     std::cerr << "Internal error:  Interface \"" << iface_name
520               << "\" not available.\n";
521     exit(OTHER_ERROR);
522   }
523 
524     // get field width for format description
525   size_t w = 0;
526   for (i = set->begin(); i != set->end(); ++i)
527     if (i->description().length() > w)
528       w = i->description().length();
529 
530     // write table header
531   str << "Format  " << std::setw(w) << std::left << "Description"
532       << "  Read  Write  File Name Suffixes\n"
533       << "------  " << std::setw(w) << std::setfill('-') << "" << std::setfill(' ')
534       << "  ----  -----  ------------------\n";
535 
536     // write table data
537   for (i = set->begin(); i != set->end(); ++i)
538   {
539     std::vector<std::string> ext;
540     i->get_extensions( ext );
541     str << std::setw(6) << i->name() << "  "
542         << std::setw(w) << std::left << i->description() << "  "
543         << (i->have_reader() ?  " yes" :  "  no") << "  "
544         << (i->have_writer() ? "  yes" : "   no") << " ";
545     for (std::vector<std::string>::iterator j = ext.begin(); j != ext.end(); ++j)
546       str << " " << *j;
547     str << std::endl;
548   }
549   str << std::endl;
550 
551   gMB->release_interface( set );
552   exit(0);
553 }
554 
usage_error(const char * name)555 static void usage_error( const char* name )
556 {
557   print_usage( name, std::cerr );
558 #ifdef MOAB_HAVE_MPI
559   MPI_Finalize();
560 #endif
561   exit(USAGE_ERROR);
562 }
563 
print_time(int clk_per_sec,const char * prefix,clock_t ticks,std::ostream & stream)564 static void print_time( int clk_per_sec, const char* prefix, clock_t ticks, std::ostream& stream )
565 {
566   ticks *= clk_per_sec/100;
567   clock_t centi = ticks % 100;
568   clock_t seconds = ticks / 100;
569   stream << prefix;
570   if (seconds < 120)
571   {
572     stream << (ticks / 100) << "." << centi << "s" << std::endl;
573   }
574   else
575   {
576     clock_t minutes = (seconds / 60) % 60;
577     clock_t hours = (seconds / 3600);
578     seconds %= 60;
579     if (hours)
580       stream << hours << "h";
581     if (minutes)
582       stream << minutes << "m";
583     if (seconds || centi)
584       stream << seconds << "." << centi << "s";
585     stream << " (" << (ticks/100) << "." << centi << "s)" << std::endl;
586   }
587 }
588 
589 clock_t usr_time, sys_time, abs_time;
590 
591 #ifdef WIN32
592 
reset_times()593 void reset_times()
594 {
595   abs_time = clock();
596 }
597 
598 
write_times(std::ostream & stream)599 void write_times( std::ostream& stream )
600 {
601   clock_t abs_tm = clock();
602   print_time( CLOCKS_PER_SEC, "  ", abs_tm - abs_time, stream );
603   abs_time = abs_tm;
604 }
605 
606 #else
607 
reset_times()608 void reset_times()
609 {
610   tms timebuf;
611   abs_time = times( &timebuf );
612   usr_time = timebuf.tms_utime;
613   sys_time = timebuf.tms_stime;
614 }
615 
write_times(std::ostream & stream)616 void write_times( std::ostream& stream )
617 {
618   clock_t usr_tm, sys_tm, abs_tm;
619   tms timebuf;
620   abs_tm = times( &timebuf );
621   usr_tm = timebuf.tms_utime;
622   sys_tm = timebuf.tms_stime;
623   print_time( sysconf(_SC_CLK_TCK), "  real:   ", abs_tm - abs_time, stream );
624   print_time( sysconf(_SC_CLK_TCK), "  user:   ", usr_tm - usr_time, stream );
625   print_time( sysconf(_SC_CLK_TCK), "  system: ", sys_tm - sys_time, stream );
626   abs_time = abs_tm;
627   usr_time = usr_tm;
628   sys_time = sys_tm;
629 }
630 
631 #endif
632 
633 const char* geom_type_names[] = { "Vertex", "Curve", "Surface", "Volume" } ;
634 const char* mesh_type_names[] = { "Dirichlet Set", "Neumann Set", "Material Set" };
635 const char* mesh_type_tags[] = { DIRICHLET_SET_TAG_NAME, NEUMANN_SET_TAG_NAME, MATERIAL_SET_TAG_NAME };
636 
main(int argc,char * argv[])637 int main( int argc, char* argv[] )
638 {
639   bool geom_owners = false;
640   bool mesh_owners = false;
641   bool just_list = false;
642   bool just_list_basic = false;
643   bool tag_count = false;
644   std::vector<std::string> file_list;
645   set_stats total_stats, file_stats;
646   std::vector<TagCounts> total_counts, file_counts;
647   ErrorCode rval;
648 
649   Range range;
650 
651   int i;
652   std::vector<std::string> read_opts;
653 
654   int proc_id = 0;
655 #ifdef MOAB_HAVE_MPI
656   MPI_Init(&argc,&argv);
657   MPI_Comm_rank( MPI_COMM_WORLD, &proc_id );
658 #endif
659 
660     // scan arguments
661   bool do_flag = true;
662   bool print_times = false;
663   bool parallel = false, resolve_shared = false, exchange_ghosts = false;
664   bool printed_usage = false;
665   for (i = 1; i < argc; i++)
666   {
667     if (!argv[i][0])
668       usage_error(argv[0]);
669 
670     if (do_flag && argv[i][0] == '-')
671     {
672       switch ( argv[i][1] )
673       {
674           // do flag arguments:
675         case '-': do_flag = false;       break;
676         case 'T': print_times = true;    break;
677         case 'h':
678         case 'H': print_usage( argv[0], std::cerr ); printed_usage = true; break;
679         case 'f': list_formats( &mb );   break;
680         case 'l':
681             if (strlen(argv[i]) == 2)
682               just_list_basic = true;
683             else if (strlen(argv[i]) == 3 && argv[i][2] == 'l')
684               just_list = true;
685             break;
686 #ifdef MOAB_HAVE_MPI
687         case 'p':
688             parallel = true;
689             if (argv[i][2] == '1' || argv[i][2] == '2') resolve_shared = true;
690             if (argv[i][2] == '2') exchange_ghosts = true;
691             break;
692 #endif
693         case 'g': geom_owners = true; break;
694         case 'm': mesh_owners = true; break;
695         case 't': tag_count = true; break;
696         default:
697             ++i;
698             switch ( argv[i-1][1] )
699             {
700               case 'O':  read_opts.push_back(argv[i]); break;
701               default: std::cerr << "Invalid option: " << argv[i] << std::endl;
702             }
703 
704       }
705     }
706       // do file names
707     else {
708       file_list.push_back( argv[i] );
709     }
710   }
711 
712     // construct options string from individual options
713   std::string read_options;
714   if (parallel) {
715     read_opts.push_back("PARALLEL=READ_PART");
716     read_opts.push_back("PARTITION=PARALLEL_PARTITION");
717   }
718   if (resolve_shared) read_opts.push_back("PARALLEL_RESOLVE_SHARED_ENTS");
719   if (exchange_ghosts) read_opts.push_back("PARALLEL_GHOSTS=3.0.1");
720 
721   if (!make_opts_string(  read_opts,  read_options ))
722   {
723 #ifdef MOAB_HAVE_MPI
724     MPI_Finalize();
725 #endif
726     return USAGE_ERROR;
727   }
728 
729   if (file_list.empty() && !printed_usage)
730     print_usage(argv[0], std::cerr);
731 
732   for (std::vector<std::string>::iterator f = file_list.begin(); f != file_list.end(); ++f)
733   {
734     reset_times();
735     printf("File %s:\n", f->c_str() );
736     if (MB_SUCCESS != mb.load_file( f->c_str(), NULL, read_options.c_str() ))
737     {
738       fprintf(stderr, "Error reading file: %s\n", f->c_str() );
739       return 1;
740     }
741 
742     if (tag_count)
743       rval = gather_tag_counts( 0, file_counts );
744     else if (!just_list)
745       rval = gather_set_stats( 0, file_stats );
746     else
747       rval = MB_SUCCESS;
748 
749     if (MB_SUCCESS != rval)
750     {
751       fprintf(stderr, "Error processing mesh from file: %s\n", f->c_str());
752       return 1;
753     }
754 
755     if (tag_count) {
756       add_tag_counts( total_counts, file_counts );
757       print_tag_counts( file_counts );
758       file_counts.clear();
759     }
760     else if (just_list) {
761       mb.list_entities( 0, -1 );
762     }
763     else {
764       total_stats.add( file_stats );
765       print_stats( file_stats );
766       file_stats.clear();
767     }
768 
769     if (geom_owners)
770     {
771       Range entities;
772       Tag dim_tag = 0, id_tag = 0;
773       rval = mb.tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, dim_tag );
774       if (MB_TAG_NOT_FOUND == rval)
775       {
776         fprintf( stderr, "No geometry tag defined.\n" );
777       }
778       else if (MB_SUCCESS != rval)
779       {
780         fprintf( stderr, "Error retreiving geometry tag.\n");
781         return 2;
782       }
783 
784       rval = mb.tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag );
785       if (MB_TAG_NOT_FOUND == rval)
786       {
787         fprintf( stderr, "No ID tag defined.\n" );
788       }
789       else if (MB_SUCCESS != rval)
790       {
791         fprintf( stderr, "Error retreiving ID tag.\n");
792         return 2;
793       }
794 
795       if (dim_tag && id_tag)
796       {
797         if (MB_SUCCESS != mb.get_entities_by_type_and_tag( 0,
798                                                         MBENTITYSET,
799                                                         &dim_tag,
800                                                         0,
801                                                         1,
802                                                         entities ))
803         {
804           fprintf( stderr, "Error retreiving geometry entitities.\n" );
805         }
806       }
807 
808       if (entities.empty())
809       {
810         fprintf( stderr, "No geometry entities defined in file.\n" );
811       }
812 
813       for (Range::iterator rit = entities.begin(); rit != entities.end(); ++rit)
814       {
815         int id = 0, dim = 0;
816         if (MB_SUCCESS != mb.tag_get_data( dim_tag, &*rit, 1, &dim ) ||
817             MB_SUCCESS != mb.tag_get_data(  id_tag, &*rit, 1,  &id ))
818         {
819           fprintf( stderr, "Error retreiving tag data for geometry entity.\n");
820           continue;
821         }
822 
823         printf( "%s %d:\n", geom_type_names[dim], id );
824         if (tag_count)
825           rval = gather_tag_counts( *rit, file_counts );
826         else if (!just_list && !just_list_basic)
827           rval = gather_set_stats( *rit, file_stats );
828 
829         if (MB_SUCCESS != rval)
830           fprintf(stderr, "Error processing mesh from file: %s\n", f->c_str());
831         else if (tag_count)
832           print_tag_counts( file_counts );
833         else if (just_list)
834           mb.list_entities( 0, 1 );
835         else if (just_list_basic)
836           mb.list_entities( 0, 0 );
837         else
838           print_stats( file_stats );
839 
840         file_stats.clear();
841         file_counts.clear();
842       }
843     }
844 
845 
846     if (mesh_owners)
847     {
848       for (int t = 0; t < 3; ++t)
849       {
850         Range entities;
851         Tag tag = 0;
852         rval = mb.tag_get_handle( mesh_type_tags[t], 1, MB_TYPE_INTEGER, tag );
853         if (MB_TAG_NOT_FOUND == rval)
854         {
855           continue;
856         }
857         else if (MB_SUCCESS != rval)
858         {
859           fprintf( stderr, "Error retreiving %s tag.\n", mesh_type_tags[t]);
860           return 2;
861         }
862 
863         if (MB_SUCCESS != mb.get_entities_by_type_and_tag( 0,
864                                                         MBENTITYSET,
865                                                         &tag,
866                                                         0,
867                                                         1,
868                                                         entities ))
869         {
870           fprintf( stderr, "Error retreiving %s entitities.\n", mesh_type_names[t] );
871           continue;
872         }
873 
874         for (Range::iterator rit = entities.begin(); rit != entities.end(); ++rit)
875         {
876           int id = 0;
877           if (MB_SUCCESS != mb.tag_get_data( tag, &*rit, 1, &id ))
878           {
879             fprintf( stderr, "Error retreiving tag data for %s entity.\n", mesh_type_names[t]);
880             continue;
881           }
882 
883           printf( "%s %d:\n", mesh_type_names[t], id );
884           if (tag_count) {
885             rval = gather_tag_counts( *rit, file_counts );
886             if (MB_SUCCESS != rval)
887               fprintf(stderr, "Error processing tags from file: %s\n", f->c_str());
888             else
889               print_tag_counts( file_counts );
890           }
891           else if (just_list)
892             mb.list_entities( 0, 1 );
893           else if (just_list_basic)
894             mb.list_entities( 0, 0 );
895           else if (!just_list && !just_list_basic) {
896             rval = gather_set_stats( *rit, file_stats );
897 
898             if (rval != MB_SUCCESS)
899               fprintf(stderr, "Error processing mesh from file: %s\n", f->c_str());
900             else
901               print_stats( file_stats );
902           }
903           file_stats.clear();
904           file_counts.clear();
905         }
906       }
907     }
908 
909     if (print_times && !proc_id) write_times( std::cout );
910     mb.delete_mesh();
911   }
912 
913   if (file_list.size() > 1 && !just_list && !just_list_basic)
914   {
915     printf("Total for all files:\n");
916     if (tag_count)
917       print_tag_counts( total_counts );
918     else
919       print_stats( total_stats );
920   }
921 #ifdef MOAB_HAVE_MPI
922   MPI_Finalize();
923 #endif
924   return 0;
925 }
926 
927 
928