Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
DirectAccessNoHoles.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 DirectAccessNoHoles.cpp:

Go to the source code of this file.

Functions

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

Function Documentation

◆ create_mesh_no_holes()

ErrorCode create_mesh_no_holes ( Interface mbImpl,
int  nquads 
)
Examples
DirectAccessNoHoles.cpp.

Definition at line 160 of file DirectAccessNoHoles.cpp.

161 {
162  // First make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are
163  // numbered in layers
164  ReadUtilIface* read_iface;
165  ErrorCode rval = mbImpl->query_interface( read_iface );MB_CHK_SET_ERR( rval, "Error in query_interface" );
166  vector< double* > coords;
167  EntityHandle start_vert, start_elem, *connect;
168  // Create verts, num is 2(nquads+1) because they're in a 1d row; will initialize coords in loop
169  // over quads later
170  rval = read_iface->get_node_coords( 3, 2 * ( nquads + 1 ), 0, start_vert, coords );MB_CHK_SET_ERR( rval, "Error in get_node_arrays" );
171  // Create quads
172  rval = read_iface->get_element_connect( nquads, 4, MBQUAD, 0, start_elem, connect );MB_CHK_SET_ERR( rval, "Error in get_element_connect" );
173  for( int i = 0; i < nquads; i++ )
174  {
175  coords[0][2 * i] = coords[0][2 * i + 1] = (double)i; // x values are all i
176  coords[1][2 * i] = 0.0;
177  coords[1][2 * i + 1] = 1.0; // y coords
178  coords[2][2 * i] = coords[2][2 * i + 1] = (double)0.0; // z values, all zero (2d mesh)
179  EntityHandle quad_v = start_vert + 2 * i;
180  connect[4 * i + 0] = quad_v;
181  connect[4 * i + 1] = quad_v + 2;
182  connect[4 * i + 2] = quad_v + 3;
183  connect[4 * i + 3] = quad_v + 1;
184  }
185 
186  // Last two vertices
187  // Cppcheck warning (false positive): variable coords is assigned a value that is never used
188  coords[0][2 * nquads] = coords[0][2 * nquads + 1] = (double)nquads;
189  coords[1][2 * nquads] = 0.0;
190  coords[1][2 * nquads + 1] = 1.0; // y coords
191  coords[2][2 * nquads] = coords[2][2 * nquads + 1] = (double)0.0; // z values, all zero (2d mesh)
192 
193  // Call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB
194  Range dum_range;
195  rval = mbImpl->get_adjacencies( &start_vert, 1, 2, false, dum_range );MB_CHK_SET_ERR( rval, "Error in get_adjacencies" );
196  assert( !dum_range.empty() );
197 
198  return MB_SUCCESS;
199 }

References moab::Range::empty(), ErrorCode, moab::Interface::get_adjacencies(), 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
DirectAccessNoHoles.cpp.

Definition at line 47 of file DirectAccessNoHoles.cpp.

48 {
49  // Get MOAB instance
50  Interface* mbImpl = new( std::nothrow ) Core;
51  if( NULL == mbImpl ) return 1;
52 
53  int nquads = 1000;
54 
55  // Parse options
56  ProgOptions opts;
57  opts.addOpt< int >( string( "nquads,n" ), string( "Number of quads in the mesh (default = 1000" ), &nquads );
58  opts.parseCommandLine( argc, argv );
59 
60  // Create simple structured mesh with hole, but using unstructured representation
61  ErrorCode rval = create_mesh_no_holes( mbImpl, nquads );MB_CHK_SET_ERR( rval, "Trouble creating mesh" );
62 
63  // Get all vertices and non-vertex entities
64  Range verts, quads;
65  rval = mbImpl->get_entities_by_handle( 0, quads );MB_CHK_SET_ERR( rval, "Trouble getting all entities" );
66  verts = quads.subset_by_dimension( 0 );
67  quads -= verts;
68 
69  // Create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts)
70  Tag tag1, tag2, tag3;
71  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" );
72  double def_val[3] = { 0.0, 0.0, 0.0 }; // need a default value for tag2 because we sum into it
73  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" );
74  int def_val_int = 0; // need a default value for tag3 because we increment it
75  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" );
76 
77  // Get pointers to connectivity, coordinate, tag, and adjacency arrays; each of these returns a
78  // count, which should be compared to the # entities you expect to verify there's only one chunk
79  // (no holes)
80  int count, vpere;
81  EntityHandle* conn_ptr;
82  rval = mbImpl->connect_iterate( quads.begin(), quads.end(), conn_ptr, vpere, count );MB_CHK_SET_ERR( rval, "Error in connect_iterate" );
83  assert( count == (int)quads.size() ); // Should end up with just one contiguous chunk of quads
84 
85  double *x_ptr, *y_ptr, *z_ptr;
86  rval = mbImpl->coords_iterate( verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count );MB_CHK_SET_ERR( rval, "Error in coords_iterate" );
87  assert( count == (int)verts.size() ); // Should end up with just one contiguous chunk of vertices
88 
89  double *tag1_ptr, *tag2_ptr;
90  int* tag3_ptr;
91  rval = mbImpl->tag_iterate( tag1, quads.begin(), quads.end(), count, (void*&)tag1_ptr );MB_CHK_SET_ERR( rval, "Error in tag1_iterate" );
92  assert( count == (int)quads.size() ); // Should end up with just one contiguous chunk of quads
93  rval = mbImpl->tag_iterate( tag2, quads.begin(), quads.end(), count, (void*&)tag2_ptr );MB_CHK_SET_ERR( rval, "Error in tag2_iterate" );
94  assert( count == (int)quads.size() ); // Should end up with just one contiguous chunk of quads
95  rval = mbImpl->tag_iterate( tag3, quads.begin(), quads.end(), count, (void*&)tag3_ptr );MB_CHK_SET_ERR( rval, "Error in tag3_iterate" );
96  assert( count == (int)quads.size() ); // Should end up with just one contiguous chunk of quads
97 
98  const vector< EntityHandle >** adjs_ptr;
99  rval = mbImpl->adjacencies_iterate( verts.begin(), verts.end(), adjs_ptr, count );MB_CHK_SET_ERR( rval, "Error in adjacencies_iterate" );
100  assert( count == (int)verts.size() ); // Should end up with just one contiguous chunk of vertices
101  // Start_ handles used to compute indices into vertex/quad arrays; can use direct subtraction
102  // because we know there aren't any holes in the handle spaces for verts or quads
103  EntityHandle start_vert = *verts.begin(), start_quad = *quads.begin();
104 
105  // Iterate over elements, computing tag1 from coords positions
106  for( int i = 0; i < nquads; i++ )
107  {
108  tag1_ptr[3 * i + 0] = tag1_ptr[3 * i + 1] = tag1_ptr[3 * i + 2] = 0.0; // Initialize position for this element
109  for( int j = 0; j < vpere; j++ )
110  { // Loop over vertices in this element
111  int v_index = conn_ptr[vpere * i + j] - start_vert; // vert index is just the offset from start vertex
112  tag1_ptr[3 * i + 0] += x_ptr[v_index];
113  tag1_ptr[3 * i + 1] += y_ptr[v_index]; // Sum vertex positions into tag1...
114  tag1_ptr[3 * i + 2] += z_ptr[v_index];
115  }
116  tag1_ptr[3 * i + 0] /= vpere;
117  tag1_ptr[3 * i + 1] /= vpere; // Then normalize
118  tag1_ptr[3 * i + 2] /= vpere;
119  } // Loop over elements in chunk
120 
121  // Iterate through vertices, summing positions into tag2 on connected elements and incrementing
122  // vertex count
123  for( int v = 0; v < count; v++ )
124  {
125  const vector< EntityHandle >* avec = *( adjs_ptr + v );
126  for( vector< EntityHandle >::const_iterator ait = avec->begin(); ait != avec->end(); ++ait )
127  {
128  // *ait is the quad handle, its index is computed by subtracting the start quad handle
129  int a_ind = *ait - start_quad;
130  tag2_ptr[3 * a_ind + 0] += x_ptr[v]; // Tag on each element is 3 doubles, x/y/z
131  tag2_ptr[3 * a_ind + 1] += y_ptr[v];
132  tag2_ptr[3 * a_ind + 2] += z_ptr[v];
133  tag3_ptr[a_ind]++; // Increment the vertex count
134  }
135  }
136 
137  // Normalize tag2 by vertex count (tag3); loop over elements using same approach as before
138  // At the same time, compare values of tag1 and tag2
139  int n_dis = 0;
140  for( Range::iterator q_it = quads.begin(); q_it != quads.end(); ++q_it )
141  {
142  int i = *q_it - start_quad;
143  for( int j = 0; j < 3; j++ )
144  tag2_ptr[3 * i + j] /= (double)tag3_ptr[i]; // Normalize by # verts
145  if( tag1_ptr[3 * i] != tag2_ptr[3 * i] || tag1_ptr[3 * i + 1] != tag2_ptr[3 * i + 1] ||
146  tag1_ptr[3 * i + 2] != tag2_ptr[3 * i + 2] )
147  {
148  cout << "Tag1, tag2 disagree for element " << *q_it + i << endl;
149  n_dis++;
150  }
151  }
152  if( !n_dis ) cout << "All tags agree, success!" << endl;
153 
154  // Ok, we're done, shut down MOAB
155  delete mbImpl;
156 
157  return 0;
158 }

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