#include "moab/Core.hpp"
#include "moab/ProgOptions.hpp"
#include "moab/ReadUtilIface.hpp"
#include <map>
#include <iostream>
#include <cassert>
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) |
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().
int main | ( | int | argc, |
char ** | argv | ||
) |
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().