MOAB: Mesh Oriented datABase  (version 5.5.0)
perftool.cpp File Reference
#include <cmath>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cassert>
#include <list>
#include "moab/Core.hpp"
#include "moab/Skinner.hpp"
#include "moab/ReadUtilIface.hpp"
+ Include dependency graph for perftool.cpp:

Go to the source code of this file.

Typedefs

typedef void(* test_func_t) (int, int, int)
 

Functions

void create_regular_mesh (int interval, int dimension)
 
void skin_common (int interval, int dim, int blocks, bool use_adj)
 
void skin (int intervals, int dim, int num)
 
void skin_adj (int intervals, int dim, int num)
 
void tag_time (TagType storage, bool direct, int intervals, int dim, int blocks)
 
void dense_tag (int intervals, int dim, int blocks)
 
void sparse_tag (int intervals, int dim, int blocks)
 
void direct_tag (int intervals, int dim, int blocks)
 
void usage (const char *argv0, bool error=true)
 
void list_tests ()
 
int main (int argc, char *argv[])
 
void create_regular_mesh (Interface *gMB, int interval, int dim)
 

Variables

double LENGTH = 1.0
 
const int DEFAULT_INTERVALS = 50
 
struct {
   std::string   testName
 
   test_func_t   testFunc
 
   std::string   testDesc
 
TestList []
 
const int TestListSize = sizeof( TestList ) / sizeof( TestList[0] )
 

Typedef Documentation

◆ test_func_t

typedef void( * test_func_t) (int, int, int)

Definition at line 65 of file perftool.cpp.

Function Documentation

◆ create_regular_mesh() [1/2]

void create_regular_mesh ( int  interval,
int  dimension 
)

Referenced by skin_common(), and tag_time().

◆ create_regular_mesh() [2/2]

void create_regular_mesh ( Interface gMB,
int  interval,
int  dim 
)

Definition at line 220 of file perftool.cpp.

221 {
222  if( dim < 1 || dim > 3 || interval < 1 )
223  {
224  std::cerr << "Invalid arguments" << std::endl;
225  exit( 1 );
226  }
227 
228  const int nvi = interval + 1;
229  const int dims[3] = { nvi, dim > 1 ? nvi : 1, dim > 2 ? nvi : 1 };
230  int num_vert = dims[0] * dims[1] * dims[2];
231 
232  ReadUtilIface* readMeshIface;
233  gMB->query_interface( readMeshIface );
234 
235  EntityHandle vstart;
236  std::vector< double* > arrays;
237  ErrorCode rval = readMeshIface->get_node_coords( 3, num_vert, 1, vstart, arrays );
238  if( MB_SUCCESS != rval || arrays.size() < 3 )
239  {
240  std::cerr << "Vertex creation failed" << std::endl;
241  exit( 2 );
242  }
243  double *x = arrays[0], *y = arrays[1], *z = arrays[2];
244 
245  // Calculate vertex coordinates
246  for( int k = 0; k < dims[2]; ++k )
247  for( int j = 0; j < dims[1]; ++j )
248  for( int i = 0; i < dims[0]; ++i )
249  {
250  *x = i;
251  ++x;
252  *y = j;
253  ++y;
254  *z = k;
255  ++z;
256  }
257 
258  const long vert_per_elem = 1 << dim; // 2^dim
259  const long intervals[3] = { interval, dim > 1 ? interval : 1, dim > 2 ? interval : 1 };
260  const long num_elem = intervals[0] * intervals[1] * intervals[2];
261  const EntityType type = ( dim == 1 ) ? MBEDGE : ( dim == 2 ) ? MBQUAD : MBHEX;
262 
263  EntityHandle estart, *conn = 0;
264  rval = readMeshIface->get_element_connect( num_elem, vert_per_elem, type, 0, estart, conn );
265  if( MB_SUCCESS != rval || !conn )
266  {
267  std::cerr << "Element creation failed" << std::endl;
268  exit( 2 );
269  }
270 
271  // Offsets of element vertices in grid relative to corner closest to origin
272  long c = dims[0] * dims[1];
273  const long corners[8] = { 0, 1, 1 + dims[0], dims[0], c, c + 1, c + 1 + dims[0], c + dims[0] };
274 
275  // Populate element list
276  EntityHandle* iter = conn;
277  for( long z1 = 0; z1 < intervals[2]; ++z1 )
278  for( long y1 = 0; y1 < intervals[1]; ++y1 )
279  for( long x1 = 0; x1 < intervals[0]; ++x1 )
280  {
281  const long index = x1 + y1 * dims[0] + z1 * ( dims[0] * dims[1] );
282  for( long j = 0; j < vert_per_elem; ++j, ++iter )
283  *iter = index + corners[j] + vstart;
284  }
285 
286  // notify MOAB of the new elements
287  rval = readMeshIface->update_adjacencies( estart, num_elem, vert_per_elem, conn );
288  if( MB_SUCCESS != rval )
289  {
290  std::cerr << "Element update failed" << std::endl;
291  exit( 2 );
292  }
293 }

References dim, ErrorCode, moab::ReadUtilIface::get_element_connect(), moab::ReadUtilIface::get_node_coords(), gMB, MB_SUCCESS, MBEDGE, MBHEX, MBQUAD, moab::Interface::query_interface(), and moab::ReadUtilIface::update_adjacencies().

◆ dense_tag()

void dense_tag ( int  intervals,
int  dim,
int  blocks 
)

Definition at line 49 of file perftool.cpp.

50 {
51  std::cout << "Dense Tag Time:";
52  tag_time( MB_TAG_DENSE, false, intervals, dim, blocks );
53 }

References dim, MB_TAG_DENSE, and tag_time().

◆ direct_tag()

void direct_tag ( int  intervals,
int  dim,
int  blocks 
)

Definition at line 59 of file perftool.cpp.

60 {
61  std::cout << "Direct Tag Time:";
62  tag_time( MB_TAG_DENSE, true, intervals, dim, blocks );
63 }

References dim, MB_TAG_DENSE, and tag_time().

◆ list_tests()

void list_tests ( )

Definition at line 96 of file perftool.cpp.

97 {
98  unsigned max_test_name = 0, max_test_desc = 0;
99  for( int i = 0; i < TestListSize; ++i )
100  {
101  if( TestList[i].testName.size() > max_test_name ) max_test_name = TestList[i].testName.size();
102  if( TestList[i].testDesc.size() > max_test_desc ) max_test_desc = TestList[i].testDesc.size();
103  }
104  std::cout << std::setw( max_test_name ) << "NAME"
105  << " " << std::setw( max_test_desc ) << std::left << "DESCRIPTION" << std::endl
106  << std::setfill( '-' ) << std::setw( max_test_name ) << ""
107  << " " << std::setfill( '-' ) << std::setw( max_test_desc ) << "" << std::setfill( ' ' ) << std::endl;
108  for( int i = 0; i < TestListSize; ++i )
109  std::cout << std::setw( max_test_name ) << TestList[i].testName << " : " << std::setw( max_test_desc )
110  << std::left << TestList[i].testDesc << std::endl;
111 }

References testDesc, TestList, TestListSize, and testName.

Referenced by main(), and runner_run_tests().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 113 of file perftool.cpp.

114 {
115  int intervals = DEFAULT_INTERVALS;
116  int dimension = 3;
117  int number = 0;
118  std::vector< test_func_t > test_list;
119  std::list< int* > expected_list;
120  bool did_help = false;
121  for( int i = 1; i < argc; ++i )
122  {
123  if( !expected_list.empty() )
124  {
125  int* ptr = expected_list.front();
126  expected_list.pop_front();
127  char* endptr;
128  *ptr = strtol( argv[i], &endptr, 0 );
129  if( !endptr )
130  {
131  usage( argv[0] );
132  std::cerr << "Expected integer value, got \"" << argv[i] << '"' << std::endl;
133  return 1;
134  }
135  }
136  else if( *argv[i] == '-' )
137  { // flag
138  for( int j = 1; argv[i][j]; ++j )
139  {
140  switch( argv[i][j] )
141  {
142  case 'i':
143  expected_list.push_back( &intervals );
144  break;
145  case 'd':
146  expected_list.push_back( &dimension );
147  break;
148  case 'n':
149  expected_list.push_back( &number );
150  break;
151  case 'h':
152  did_help = true;
153  usage( argv[0], false );
154  break;
155  case 'l':
156  did_help = true;
157  list_tests();
158  break;
159  default:
160  usage( argv[0] );
161  std::cerr << "Invalid option: -" << argv[i][j] << std::endl;
162  return 1;
163  }
164  }
165  }
166  else
167  {
168  int j = -1;
169  do
170  {
171  ++j;
172  if( j >= TestListSize )
173  {
174  usage( argv[0] );
175  std::cerr << "Invalid test name: " << argv[i] << std::endl;
176  return 1;
177  }
178  } while( TestList[j].testName != argv[i] );
179  test_list.push_back( TestList[j].testFunc );
180  }
181  }
182 
183  if( !expected_list.empty() )
184  {
185  usage( argv[0] );
186  std::cerr << "Missing final argument" << std::endl;
187  return 1;
188  }
189 
190  // error if no input
191  if( test_list.empty() && !did_help )
192  {
193  usage( argv[0] );
194  std::cerr << "No tests specified" << std::endl;
195  return 1;
196  }
197 
198  if( intervals < 1 )
199  {
200  std::cerr << "Invalid interval count: " << intervals << std::endl;
201  return 1;
202  }
203 
204  if( dimension < 1 || dimension > 3 )
205  {
206  std::cerr << "Invalid dimension: " << dimension << std::endl;
207  return 1;
208  }
209 
210  // now run the tests
211  for( std::vector< test_func_t >::iterator i = test_list.begin(); i != test_list.end(); ++i )
212  {
213  test_func_t fptr = *i;
214  fptr( intervals, dimension, number );
215  }
216 
217  return 0;
218 }

References DEFAULT_INTERVALS, list_tests(), testFunc, TestList, TestListSize, testName, and usage().

◆ skin()

◆ skin_adj()

void skin_adj ( int  intervals,
int  dim,
int  num 
)

Definition at line 41 of file perftool.cpp.

42 {
43  std::cout << "Skinning with adjacencies:" << std::endl;
44  skin_common( intervals, dim, num, true );
45 }

References dim, and skin_common().

◆ skin_common()

void skin_common ( int  interval,
int  dim,
int  blocks,
bool  use_adj 
)

Definition at line 295 of file perftool.cpp.

296 {
297  Core moab;
298  Interface* gMB = &moab;
299  ErrorCode rval;
300  double d;
301  clock_t t, tt;
302 
303  create_regular_mesh( gMB, interval, dim );
304 
305  Range skin, verts, elems;
306  rval = gMB->get_entities_by_dimension( 0, dim, elems );
307  assert( MB_SUCCESS == rval );
308  assert( !elems.empty() );
309 
310  Skinner tool( gMB );
311 
312  t = clock();
313  rval = tool.find_skin( 0, elems, true, verts, 0, use_adj, false );
314  t = clock() - t;
315  if( MB_SUCCESS != rval )
316  {
317  std::cerr << "Search for skin vertices failed" << std::endl;
318  exit( 2 );
319  }
320  d = ( (double)t ) / CLOCKS_PER_SEC;
321  std::cout << "Got " << verts.size() << " skin vertices in " << d << " seconds." << std::endl;
322 
323  t = 0;
324  if( num < 1 ) num = 1000;
325  long blocksize = elems.size() / num;
326  if( !blocksize ) blocksize = 1;
327  long numblocks = elems.size() / blocksize;
328  Range::iterator it = elems.begin();
329  for( long i = 0; i < numblocks; ++i )
330  {
331  verts.clear();
332  Range::iterator end = it + blocksize;
333  Range blockelems;
334  blockelems.merge( it, end );
335  it = end;
336  tt = clock();
337  rval = tool.find_skin( 0, blockelems, true, verts, 0, use_adj, false );
338  t += clock() - tt;
339  if( MB_SUCCESS != rval )
340  {
341  std::cerr << "Search for skin vertices failed" << std::endl;
342  exit( 2 );
343  }
344  }
345  d = ( (double)t ) / CLOCKS_PER_SEC;
346  std::cout << "Got skin vertices for " << numblocks << " blocks of " << blocksize << " elements in " << d
347  << " seconds." << std::endl;
348 
349  for( int e = 0; e < 2; ++e )
350  { // do this twice
351  if( e == 1 )
352  {
353  // create all interior faces
354  skin.clear();
355  t = clock();
356  gMB->get_adjacencies( elems, dim - 1, true, skin, Interface::UNION );
357  t = clock() - t;
358  d = ( (double)t ) / CLOCKS_PER_SEC;
359  std::cout << "Created " << skin.size() << " entities of dimension-1 in " << d << " seconds" << std::endl;
360  }
361 
362  skin.clear();
363  t = clock();
364  rval = tool.find_skin( 0, elems, false, skin, 0, use_adj, true );
365  t = clock() - t;
366  if( MB_SUCCESS != rval )
367  {
368  std::cerr << "Search for skin vertices failed" << std::endl;
369  exit( 2 );
370  }
371  d = ( (double)t ) / CLOCKS_PER_SEC;
372  std::cout << "Got " << skin.size() << " skin elements in " << d << " seconds." << std::endl;
373 
374  t = 0;
375  it = elems.begin();
376  for( long i = 0; i < numblocks; ++i )
377  {
378  skin.clear();
379  Range::iterator end = it + blocksize;
380  Range blockelems;
381  blockelems.merge( it, end );
382  it = end;
383  tt = clock();
384  rval = tool.find_skin( 0, blockelems, false, skin, 0, use_adj, true );
385  t += clock() - tt;
386  if( MB_SUCCESS != rval )
387  {
388  std::cerr << "Search for skin elements failed" << std::endl;
389  exit( 2 );
390  }
391  }
392  d = ( (double)t ) / CLOCKS_PER_SEC;
393  std::cout << "Got skin elements for " << numblocks << " blocks of " << blocksize << " elements in " << d
394  << " seconds." << std::endl;
395  }
396 }

References moab::Range::begin(), moab::Range::clear(), create_regular_mesh(), dim, moab::Range::empty(), ErrorCode, moab::Skinner::find_skin(), moab::Interface::get_adjacencies(), moab::Interface::get_entities_by_dimension(), gMB, MB_SUCCESS, moab::Range::merge(), moab::Range::size(), skin(), t, and moab::Interface::UNION.

Referenced by skin(), and skin_adj().

◆ sparse_tag()

void sparse_tag ( int  intervals,
int  dim,
int  blocks 
)

Definition at line 54 of file perftool.cpp.

55 {
56  std::cout << "Sparse Tag Time:";
57  tag_time( MB_TAG_SPARSE, false, intervals, dim, blocks );
58 }

References dim, MB_TAG_SPARSE, and tag_time().

◆ tag_time()

void tag_time ( TagType  storage,
bool  direct,
int  intervals,
int  dim,
int  blocks 
)

Definition at line 398 of file perftool.cpp.

399 {
400  Core moab;
401  Interface& mb = moab;
402  create_regular_mesh( &mb, intervals, dim );
403 
404  // Create tag in which to store data
405  Tag tag;
406  mb.tag_get_handle( "data", 1, MB_TYPE_DOUBLE, tag, storage | MB_TAG_CREAT );
407 
408  // Make up some arbitrary iterative calculation for timing purposes:
409  // set each value v_n = (V + v_n)/2 until all values are within
410  // epsilon of V.
411  std::vector< double > data;
412  Range verts;
413  mb.get_entities_by_type( 0, MBVERTEX, verts );
414 
415  clock_t t = clock();
416 
417  // initialize
418  if( direct )
419  {
420  Range::iterator i, j = verts.begin();
421  void* ptr;
422  int count;
423  while( j != verts.end() )
424  {
425  mb.tag_iterate( tag, i, verts.end(), count, ptr );
426  double* arr = reinterpret_cast< double* >( ptr );
427  for( j = i + count; i != j; ++i, ++arr )
428  *arr = ( 11.0 * *i + 7.0 ) / ( *i );
429  }
430  }
431  else
432  {
433  data.resize( verts.size() );
434  double* arr = &data[0];
435  for( Range::iterator i = verts.begin(); i != verts.end(); ++i, ++arr )
436  *arr = ( 11.0 * *i + 7.0 ) / ( *i );
437  mb.tag_set_data( tag, verts, &data[0] );
438  }
439 
440  // iterate
441  const double v0 = acos( -1.0 ); // pi
442  size_t iter_count = 0;
443  double max_diff;
444  const size_t num_verts = verts.size();
445  do
446  {
447  if( direct )
448  {
449  max_diff = 0.0;
450  Range::iterator i, j = verts.begin();
451  void* ptr;
452  while( j != verts.end() )
453  {
454  int count;
455  mb.tag_iterate( tag, i, verts.end(), count, ptr );
456  double* arr = reinterpret_cast< double* >( ptr );
457 
458  for( j = i + count; i != j; ++i, ++arr )
459  {
460  *arr = 0.5 * ( *arr + v0 );
461  double diff = fabs( *arr - v0 );
462  if( diff > max_diff ) max_diff = diff;
463  }
464  }
465  }
466  else if( blocks < 1 )
467  {
468  max_diff = 0.0;
469  mb.tag_get_data( tag, verts, &data[0] );
470  for( size_t i = 0; i < data.size(); ++i )
471  {
472  data[i] = 0.5 * ( v0 + data[i] );
473  double diff = fabs( data[i] - v0 );
474  if( diff > max_diff ) max_diff = diff;
475  }
476  mb.tag_set_data( tag, verts, &data[0] );
477  }
478  else
479  {
480  max_diff = 0.0;
481  Range r;
482  Range::iterator it = verts.begin();
483  size_t step = num_verts / blocks;
484  for( int j = 0; j < blocks - 1; ++j )
485  {
486  Range::iterator nx = it;
487  nx += step;
488  r.clear();
489  r.merge( it, nx );
490  mb.tag_get_data( tag, r, &data[0] );
491  it = nx;
492 
493  for( size_t i = 0; i < step; ++i )
494  {
495  data[i] = 0.5 * ( v0 + data[i] );
496  double diff = fabs( data[i] - v0 );
497  if( diff > max_diff ) max_diff = diff;
498  }
499  mb.tag_set_data( tag, r, &data[0] );
500  }
501 
502  r.clear();
503  r.merge( it, verts.end() );
504  mb.tag_get_data( tag, r, &data[0] );
505  for( size_t i = 0; i < ( num_verts - ( blocks - 1 ) * step ); ++i )
506  {
507  data[i] = 0.5 * ( v0 + data[i] );
508  double diff = fabs( data[i] - v0 );
509  if( diff > max_diff ) max_diff = diff;
510  }
511  mb.tag_set_data( tag, r, &data[0] );
512  }
513  ++iter_count;
514  // std::cout << iter_count << " " << max_diff << std::endl;
515  } while( max_diff > 1e-6 );
516 
517  double secs = ( clock() - t ) / (double)CLOCKS_PER_SEC;
518  std::cout << " " << iter_count << " iterations in " << secs << " seconds" << std::endl;
519 }

References moab::Range::begin(), moab::Range::clear(), create_regular_mesh(), dim, moab::Range::end(), moab::Core::get_entities_by_type(), mb, MB_TAG_CREAT, MB_TYPE_DOUBLE, MBVERTEX, moab::Range::merge(), moab::Range::size(), t, moab::Core::tag_get_data(), moab::Core::tag_get_handle(), moab::Core::tag_iterate(), and moab::Core::tag_set_data().

Referenced by dense_tag(), direct_tag(), main(), and sparse_tag().

◆ usage()

void usage ( const char *  argv0,
bool  error = true 
)

Definition at line 80 of file perftool.cpp.

81 {
82  std::ostream& str = error ? std::cerr : std::cout;
83  str << "Usage: " << argv0
84  << " [-i <ints_per_side>] [-d <dimension>] [-n <test_specifc_int>] <test_name> "
85  "[<test_name2> ...]"
86  << std::endl;
87  str << " " << argv0 << " [-h|-l]" << std::endl;
88  if( error ) return;
89  str << " -i : specify interverals per side (num hex = ints^3, default: " << DEFAULT_INTERVALS << std::endl;
90  str << " -d : specify element dimension, default: 3" << std::endl;
91  str << " -n : specify an integer value that for which the meaning is test-specific" << std::endl;
92  str << " -h : print this help text." << std::endl;
93  str << " -l : list available tests" << std::endl;
94 }

References argv0, DEFAULT_INTERVALS, and moab::error().

Referenced by main().

Variable Documentation

◆ DEFAULT_INTERVALS

const int DEFAULT_INTERVALS = 50

Definition at line 32 of file perftool.cpp.

Referenced by main(), and usage().

◆ LENGTH

double LENGTH = 1.0

Definition at line 31 of file perftool.cpp.

◆ testDesc

std::string testDesc

Definition at line 70 of file perftool.cpp.

Referenced by list_tests().

◆ testFunc

test_func_t testFunc

Definition at line 69 of file perftool.cpp.

Referenced by main(), runner_find_test_func(), and runner_run_tests().

◆ 

const { ... } TestList[]
Initial value:
= {
{ "skin", &skin, "Test time to get skin mesh w/out adjacencies" },
{ "skin_adj", &skin_adj, "Test time to get skin mesh with adjacencies" },
{ "sparse", &sparse_tag, "Sparse tag data manipulation" },
{ "dense", &dense_tag, "Dense tag data manipulation" },
{ "direct", &direct_tag, "Dense tag data manipulation using direct data access" },
}

Referenced by list_tests(), and main().

◆ TestListSize

const int TestListSize = sizeof( TestList ) / sizeof( TestList[0] )

Definition at line 78 of file perftool.cpp.

Referenced by list_tests(), and main().

◆ testName

std::string testName