Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DirectAccessWithHoles.cpp File Reference
#include "moab/Core.hpp"
#include "moab/ProgOptions.hpp"
#include "moab/ReadUtilIface.hpp"
#include <map>
#include <iostream>
#include <cassert>
+ Include dependency graph for DirectAccessWithHoles.cpp:

Go to the source code of this file.

Classes

struct  tag_struct
 

Functions

ErrorCode create_mesh_with_holes (Interface *mbImpl, int nquads, int nholes)
 
int main (int argc, char **argv)
 

Function Documentation

◆ create_mesh_with_holes()

ErrorCode create_mesh_with_holes ( Interface mbImpl,
int  nquads,
int  nholes 
)
Examples
DirectAccessWithHoles.cpp.

Definition at line 230 of file DirectAccessWithHoles.cpp.

231 { 232  // First make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are 233  // numbered in layers 234  ReadUtilIface* read_iface; 235  ErrorCode rval = mbImpl->query_interface( read_iface );MB_CHK_SET_ERR( rval, "Error in query_interface" ); 236  vector< double* > coords; 237  EntityHandle start_vert, start_elem, *connect; 238  // Create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop 239  // over elems later 240  rval = read_iface->get_node_coords( 3, 2 * ( nquads + 1 ), 0, start_vert, coords );MB_CHK_SET_ERR( rval, "Error in get_node_arrays" ); 241  // Create elems 242  rval = read_iface->get_element_connect( nquads, 4, MBQUAD, 0, start_elem, connect );MB_CHK_SET_ERR( rval, "Error in get_element_connect" ); 243  for( int i = 0; i < nquads; i++ ) 244  { 245  coords[0][2 * i] = coords[0][2 * i + 1] = (double)i; // x values are all i 246  coords[1][2 * i] = 0.0; 247  coords[1][2 * i + 1] = 1.0; // y coords 248  coords[2][2 * i] = coords[2][2 * i + 1] = (double)0.0; // z values, all zero (2d mesh) 249  EntityHandle quad_v = start_vert + 2 * i; 250  for( int j = 0; j < 4; j++ ) 251  connect[4 * i + j] = quad_v + j; // Connectivity of each quad is a sequence starting from quad_v 252  } 253  // Last two vertices 254  // Cppcheck warning (false positive): variable coords is assigned a value that is never used 255  coords[0][2 * nquads] = coords[0][2 * nquads + 1] = (double)nquads; 256  coords[1][2 * nquads] = 0.0; 257  coords[1][2 * nquads + 1] = 1.0; // y coords 258  coords[2][2 * nquads] = coords[2][2 * nquads + 1] = (double)0.0; // z values, all zero (2d mesh) 259  260  // Now delete nholes elements, spaced approximately equally through mesh, so contiguous size is 261  // about nquads/(nholes + 1) reinterpret start_elem as the next element to be deleted 262  int de = nquads / ( nholes + 1 ); 263  for( int i = 0; i < nholes; i++ ) 264  { 265  start_elem += de; 266  rval = mbImpl->delete_entities( &start_elem, 1 );MB_CHK_SET_ERR( rval, "Error in delete_entities" ); 267  } 268  269  return MB_SUCCESS; 270 }

References moab::Interface::delete_entities(), ErrorCode, moab::ReadUtilIface::get_element_connect(), moab::ReadUtilIface::get_node_coords(), MB_CHK_SET_ERR, MB_SUCCESS, MBQUAD, and moab::Interface::query_interface().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)
Examples
DirectAccessWithHoles.cpp.

Definition at line 55 of file DirectAccessWithHoles.cpp.

56 { 57  // Get MOAB instance 58  Interface* mbImpl = new( std::nothrow ) Core; 59  if( NULL == mbImpl ) return 1; 60  61  int nquads = 1000, nholes = 1; 62  63  // Parse options 64  ProgOptions opts; 65  opts.addOpt< int >( string( "nquads,n" ), string( "Number of quads in the mesh (default = 1000" ), &nquads ); 66  opts.addOpt< int >( string( "holes,H" ), string( "Number of holes in the element handle space (default = 1" ), 67  &nholes ); 68  opts.parseCommandLine( argc, argv ); 69  if( nholes >= nquads ) 70  { 71  cerr << "Number of holes needs to be < number of elements." << endl; 72  return 1; 73  } 74  75  // Create simple structured mesh with hole, but using unstructured representation 76  ErrorCode rval = create_mesh_with_holes( mbImpl, nquads, nholes );MB_CHK_SET_ERR( rval, "Trouble creating mesh" ); 77  78  // Get all vertices and non-vertex entities 79  Range verts, elems; 80  rval = mbImpl->get_entities_by_handle( 0, elems );MB_CHK_SET_ERR( rval, "Trouble getting all entities" ); 81  verts = elems.subset_by_dimension( 0 ); 82  elems -= verts; 83  84  // Create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts) 85  Tag tag1, tag2, tag3; 86  rval = mbImpl->tag_get_handle( "tag1", 3, MB_TYPE_DOUBLE, tag1, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating tag1" ); 87  double def_val[3] = { 0.0, 0.0, 0.0 }; // Need a default value for tag2 because we sum into it 88  rval = mbImpl->tag_get_handle( "tag2", 3, MB_TYPE_DOUBLE, tag2, MB_TAG_DENSE | MB_TAG_CREAT, def_val );MB_CHK_SET_ERR( rval, "Trouble creating tag2" ); 89  int def_val_int = 0; // Need a default value for tag3 because we increment it 90  rval = mbImpl->tag_get_handle( "tag3", 1, MB_TYPE_INTEGER, tag3, MB_TAG_DENSE | MB_TAG_CREAT, &def_val_int );MB_CHK_SET_ERR( rval, "Trouble creating tag3" ); 91  92  // Get connectivity, coordinate, tag, and adjacency iterators 93  EntityHandle* conn_ptr; 94  double *x_ptr, *y_ptr, *z_ptr, *tag1_ptr, *tag2_ptr; 95  int* tag3_ptr; 96  97  // First vertex is at start of range (ranges are sorted), and is offset for vertex index 98  // calculation 99  EntityHandle first_vert = *verts.begin(); 100  101  // When iterating over elements, each chunk can have a different # vertices; also, count tells 102  // you how many elements are in the current chunk 103  int vpere, count; 104  105  // Get coordinates iterator, just need this once because we know verts handle space doesn't have 106  // holes 107  rval = mbImpl->coords_iterate( verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count );MB_CHK_SET_ERR( rval, "Error in coords_iterate" ); 108  assert( count == (int)verts.size() ); // Should end up with just one contiguous chunk of vertices 109  110  // Iterate through elements, computing midpoint based on vertex positions, set on element-based 111  // tag1 Control loop by iterator over elem range 112  Range::iterator e_it = elems.begin(); 113  114  while( e_it != elems.end() ) 115  { 116  // Get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers 117  // for all verts 118  rval = mbImpl->connect_iterate( e_it, elems.end(), conn_ptr, vpere, count );MB_CHK_SET_ERR( rval, "Error in connect_iterate" ); 119  rval = mbImpl->tag_iterate( tag1, e_it, elems.end(), count, (void*&)tag1_ptr );MB_CHK_SET_ERR( rval, "Error in tag1_iterate" ); 120  121  // Iterate over elements in this chunk 122  for( int i = 0; i < count; i++ ) 123  { 124  tag1_ptr[0] = tag1_ptr[1] = tag1_ptr[2] = 0.0; // Initialize position for this element 125  for( int j = 0; j < vpere; j++ ) 126  { // Loop over vertices in this element 127  int v_index = conn_ptr[j] - first_vert; // vert index is just the offset from first vertex 128  tag1_ptr[0] += x_ptr[v_index]; 129  tag1_ptr[1] += y_ptr[v_index]; // Sum vertex positions into tag1... 130  tag1_ptr[2] += z_ptr[v_index]; 131  } 132  tag1_ptr[0] /= vpere; 133  tag1_ptr[1] /= vpere; // Then normalize 134  tag1_ptr[2] /= vpere; 135  136  // Done with this element; advance connect_ptr and tag1_ptr to next element 137  conn_ptr += vpere; 138  tag1_ptr += 3; 139  } // Loop over elements in chunk 140  141  // Done with chunk; advance range iterator by count; will skip over gaps in range 142  e_it += count; 143  } // While loop over all elements 144  145  // Iterate through vertices, summing positions into tag2 on connected elements and incrementing 146  // vertex count Iterate over chunks the same as elements, even though we know we have only one 147  // chunk here, just to show how it's done 148  149  // Create a std::map from EntityHandle (first entity handle in chunk) to 150  // tag_struct (ptrs to start of avg/#verts tags for that chunk); then for a given entity handle, 151  // we can quickly find the chunk it's in using map::lower_bound; could have set up this map in 152  // earlier loop over elements, but do it here for clarity 153  154  map< EntityHandle, tag_struct > elem_map; 155  e_it = elems.begin(); 156  while( e_it != elems.end() ) 157  { 158  tag_struct ts = { NULL, NULL }; 159  rval = mbImpl->tag_iterate( tag2, e_it, elems.end(), count, (void*&)ts.avg_ptr );MB_CHK_SET_ERR( rval, "Error in tag2_iterate" ); 160  rval = mbImpl->tag_iterate( tag3, e_it, elems.end(), count, (void*&)ts.nv_ptr );MB_CHK_SET_ERR( rval, "Error in tag3_iterate" ); 161  elem_map[*e_it] = ts; 162  e_it += count; 163  } 164  165  // Call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB 166  Range::iterator v_it = verts.begin(); 167  Range dum_range; 168  rval = mbImpl->get_adjacencies( &( *v_it ), 1, 2, false, dum_range );MB_CHK_SET_ERR( rval, "Error in get_adjacencies" ); 169  const vector< EntityHandle >** adjs_ptr; 170  while( v_it != verts.end() ) 171  { 172  // Get coords ptrs, adjs_ptr; can't set tag2_ptr by direct access, because of hole in 173  // element handle space 174  rval = mbImpl->coords_iterate( v_it, verts.end(), x_ptr, y_ptr, z_ptr, count );MB_CHK_SET_ERR( rval, "Error in coords_iterate" ); 175  rval = mbImpl->adjacencies_iterate( v_it, verts.end(), adjs_ptr, count );MB_CHK_SET_ERR( rval, "Error in adjacencies_iterate" ); 176  177  for( int v = 0; v < count; v++ ) 178  { 179  const vector< EntityHandle >* avec = *( adjs_ptr + v ); 180  for( vector< EntityHandle >::const_iterator ait = avec->begin(); ait != avec->end(); ++ait ) 181  { 182  // Get chunk that this element resides in; upper_bound points to the first element 183  // strictly > key, so get that and decrement (would work the same as lower_bound 184  // with an if-test and decrement) 185  map< EntityHandle, tag_struct >::iterator mit = elem_map.upper_bound( *ait ); 186  --mit; 187  // Index of *ait in that chunk 188  int a_ind = *ait - ( *mit ).first; 189  tag_struct ts = ( *mit ).second; 190  ts.avg_ptr[3 * a_ind + 0] += x_ptr[v]; // Tag on each element is 3 doubles, x/y/z 191  ts.avg_ptr[3 * a_ind + 1] += y_ptr[v]; 192  ts.avg_ptr[3 * a_ind + 2] += z_ptr[v]; 193  ts.nv_ptr[a_ind]++; // Increment the vertex count 194  } 195  } 196  197  v_it += count; 198  } 199  200  // Normalize tag2 by vertex count; loop over elements using same approach as before 201  // At the same time, compare values of tag1 and tag2 202  e_it = elems.begin(); 203  while( e_it != elems.end() ) 204  { 205  // Get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers 206  // for all verts 207  rval = mbImpl->tag_iterate( tag1, e_it, elems.end(), count, (void*&)tag1_ptr );MB_CHK_SET_ERR( rval, "Error in tag1_iterate" ); 208  rval = mbImpl->tag_iterate( tag2, e_it, elems.end(), count, (void*&)tag2_ptr );MB_CHK_SET_ERR( rval, "Error in tag2_iterate" ); 209  rval = mbImpl->tag_iterate( tag3, e_it, elems.end(), count, (void*&)tag3_ptr );MB_CHK_SET_ERR( rval, "Error in tag3_iterate" ); 210  211  // Iterate over elements in this chunk 212  for( int i = 0; i < count; i++ ) 213  { 214  for( int j = 0; j < 3; j++ ) 215  tag2_ptr[3 * i + j] /= (double)tag3_ptr[i]; // Normalize by # verts 216  if( tag1_ptr[3 * i] != tag2_ptr[3 * i] || tag1_ptr[3 * i + 1] != tag2_ptr[3 * i + 1] || 217  tag1_ptr[3 * i + 2] != tag2_ptr[3 * i + 2] ) 218  cout << "Tag1, tag2 disagree for element " << *e_it + i << endl; 219  } 220  221  e_it += count; 222  } 223  224  // Ok, we're done, shut down MOAB 225  delete mbImpl; 226  227  return 0; 228 }

References ProgOptions::addOpt(), moab::Interface::adjacencies_iterate(), tag_struct::avg_ptr, moab::Range::begin(), moab::Interface::connect_iterate(), moab::Interface::coords_iterate(), create_mesh_with_holes(), moab::Range::end(), ErrorCode, moab::Interface::get_adjacencies(), moab::Interface::get_entities_by_handle(), MB_CHK_SET_ERR, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_DOUBLE, MB_TYPE_INTEGER, tag_struct::nv_ptr, ProgOptions::parseCommandLine(), moab::Range::size(), moab::Range::subset_by_dimension(), moab::Interface::tag_get_handle(), and moab::Interface::tag_iterate().