MOAB: Mesh Oriented datABase  (version 5.4.1)
DirectAccessWithHoles.cpp
Go to the documentation of this file.
00001 /** @example DirectAccessWithHoles.cpp \n
00002  * \brief Use direct access to MOAB data to avoid calling through API \n
00003  *
00004  * This example creates a 1d row of quad elements, with a user-specified number of "holes" (missing
00005  * quads) in the row: \verbatim
00006  *  ----------------------      ----------------------      --------
00007  *  |      |      |      |      |      |      |      |      |      |
00008  *  |      |      |      |(hole)|      |      |      |(hole)|      | ...
00009  *  |      |      |      |      |      |      |      |      |      |
00010  *  ----------------------      ----------------------      --------
00011  * \endverbatim
00012  * This makes (nholes+1) contiguous runs of quad handles in the handle space
00013  * This example shows how to use the xxx_iterate functions in MOAB (xxx = coords, connect, tag,
00014  * adjacencies) to get direct pointer access to MOAB internal storage, which can be used without
00015  * calling through the MOAB API.
00016  *
00017  *    -#  Initialize MOAB \n
00018  *    -#  Create a quad mesh with holes, as depicted above
00019  *    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad
00020  * (tag3)
00021  *    -#  Get connectivity, coordinate, tag1 iterators
00022  *    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based
00023  * tag1
00024  *    -#  Set up map from starting quad handle for a chunk to struct of (tag1_ptr, tag2_ptr,
00025  * tag3_ptr), pointers to the dense tag storage for those tags for the chunk
00026  *    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing
00027  * vertex count
00028  *    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and
00029  * tag2
00030  *
00031  * <b>To compile</b>: \n
00032  *    make DirectAccessWithHoles MOAB_DIR=<installdir> \n
00033  * <b>To run</b>: ./DirectAccess [-nquads <# quads>] [-holes <# holes>]\n
00034  *
00035  */
00036 
00037 #include "moab/Core.hpp"
00038 #include "moab/ProgOptions.hpp"
00039 #include "moab/ReadUtilIface.hpp"
00040 #include <map>
00041 #include <iostream>
00042 #include <cassert>
00043 
00044 using namespace moab;
00045 using namespace std;
00046 
00047 ErrorCode create_mesh_with_holes( Interface* mbImpl, int nquads, int nholes );
00048 
00049 struct tag_struct
00050 {
00051     double* avg_ptr;
00052     int* nv_ptr;
00053 };
00054 
00055 int main( int argc, char** argv )
00056 {
00057     // Get MOAB instance
00058     Interface* mbImpl = new( std::nothrow ) Core;
00059     if( NULL == mbImpl ) return 1;
00060 
00061     int nquads = 1000, nholes = 1;
00062 
00063     // Parse options
00064     ProgOptions opts;
00065     opts.addOpt< int >( string( "nquads,n" ), string( "Number of quads in the mesh (default = 1000" ), &nquads );
00066     opts.addOpt< int >( string( "holes,H" ), string( "Number of holes in the element handle space (default = 1" ),
00067                         &nholes );
00068     opts.parseCommandLine( argc, argv );
00069     if( nholes >= nquads )
00070     {
00071         cerr << "Number of holes needs to be < number of elements." << endl;
00072         return 1;
00073     }
00074 
00075     // Create simple structured mesh with hole, but using unstructured representation
00076     ErrorCode rval = create_mesh_with_holes( mbImpl, nquads, nholes );MB_CHK_SET_ERR( rval, "Trouble creating mesh" );
00077 
00078     // Get all vertices and non-vertex entities
00079     Range verts, elems;
00080     rval = mbImpl->get_entities_by_handle( 0, elems );MB_CHK_SET_ERR( rval, "Trouble getting all entities" );
00081     verts = elems.subset_by_dimension( 0 );
00082     elems -= verts;
00083 
00084     // Create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts)
00085     Tag tag1, tag2, tag3;
00086     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" );
00087     double def_val[3] = { 0.0, 0.0, 0.0 };  // Need a default value for tag2 because we sum into it
00088     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" );
00089     int def_val_int = 0;  // Need a default value for tag3 because we increment it
00090     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" );
00091 
00092     // Get connectivity, coordinate, tag, and adjacency iterators
00093     EntityHandle* conn_ptr;
00094     double *x_ptr, *y_ptr, *z_ptr, *tag1_ptr, *tag2_ptr;
00095     int* tag3_ptr;
00096 
00097     // First vertex is at start of range (ranges are sorted), and is offset for vertex index
00098     // calculation
00099     EntityHandle first_vert = *verts.begin();
00100 
00101     // When iterating over elements, each chunk can have a different # vertices; also, count tells
00102     // you how many elements are in the current chunk
00103     int vpere, count;
00104 
00105     // Get coordinates iterator, just need this once because we know verts handle space doesn't have
00106     // holes
00107     rval = mbImpl->coords_iterate( verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count );MB_CHK_SET_ERR( rval, "Error in coords_iterate" );
00108     assert( count == (int)verts.size() );  // Should end up with just one contiguous chunk of vertices
00109 
00110     // Iterate through elements, computing midpoint based on vertex positions, set on element-based
00111     // tag1 Control loop by iterator over elem range
00112     Range::iterator e_it = elems.begin();
00113 
00114     while( e_it != elems.end() )
00115     {
00116         // Get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers
00117         // for all verts
00118         rval = mbImpl->connect_iterate( e_it, elems.end(), conn_ptr, vpere, count );MB_CHK_SET_ERR( rval, "Error in connect_iterate" );
00119         rval = mbImpl->tag_iterate( tag1, e_it, elems.end(), count, (void*&)tag1_ptr );MB_CHK_SET_ERR( rval, "Error in tag1_iterate" );
00120 
00121         // Iterate over elements in this chunk
00122         for( int i = 0; i < count; i++ )
00123         {
00124             tag1_ptr[0] = tag1_ptr[1] = tag1_ptr[2] = 0.0;  // Initialize position for this element
00125             for( int j = 0; j < vpere; j++ )
00126             {                                            // Loop over vertices in this element
00127                 int v_index = conn_ptr[j] - first_vert;  // vert index is just the offset from first vertex
00128                 tag1_ptr[0] += x_ptr[v_index];
00129                 tag1_ptr[1] += y_ptr[v_index];  // Sum vertex positions into tag1...
00130                 tag1_ptr[2] += z_ptr[v_index];
00131             }
00132             tag1_ptr[0] /= vpere;
00133             tag1_ptr[1] /= vpere;  // Then normalize
00134             tag1_ptr[2] /= vpere;
00135 
00136             // Done with this element; advance connect_ptr and tag1_ptr to next element
00137             conn_ptr += vpere;
00138             tag1_ptr += 3;
00139         }  // Loop over elements in chunk
00140 
00141         // Done with chunk; advance range iterator by count; will skip over gaps in range
00142         e_it += count;
00143     }  // While loop over all elements
00144 
00145     // Iterate through vertices, summing positions into tag2 on connected elements and incrementing
00146     // vertex count Iterate over chunks the same as elements, even though we know we have only one
00147     // chunk here, just to show how it's done
00148 
00149     // Create a std::map from EntityHandle (first entity handle in chunk) to
00150     // tag_struct (ptrs to start of avg/#verts tags for that chunk); then for a given entity handle,
00151     // we can quickly find the chunk it's in using map::lower_bound; could have set up this map in
00152     // earlier loop over elements, but do it here for clarity
00153 
00154     map< EntityHandle, tag_struct > elem_map;
00155     e_it = elems.begin();
00156     while( e_it != elems.end() )
00157     {
00158         tag_struct ts = { NULL, NULL };
00159         rval          = mbImpl->tag_iterate( tag2, e_it, elems.end(), count, (void*&)ts.avg_ptr );MB_CHK_SET_ERR( rval, "Error in tag2_iterate" );
00160         rval = mbImpl->tag_iterate( tag3, e_it, elems.end(), count, (void*&)ts.nv_ptr );MB_CHK_SET_ERR( rval, "Error in tag3_iterate" );
00161         elem_map[*e_it] = ts;
00162         e_it += count;
00163     }
00164 
00165     // Call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB
00166     Range::iterator v_it = verts.begin();
00167     Range dum_range;
00168     rval = mbImpl->get_adjacencies( &( *v_it ), 1, 2, false, dum_range );MB_CHK_SET_ERR( rval, "Error in get_adjacencies" );
00169     const vector< EntityHandle >** adjs_ptr;
00170     while( v_it != verts.end() )
00171     {
00172         // Get coords ptrs, adjs_ptr; can't set tag2_ptr by direct access, because of hole in
00173         // element handle space
00174         rval = mbImpl->coords_iterate( v_it, verts.end(), x_ptr, y_ptr, z_ptr, count );MB_CHK_SET_ERR( rval, "Error in coords_iterate" );
00175         rval = mbImpl->adjacencies_iterate( v_it, verts.end(), adjs_ptr, count );MB_CHK_SET_ERR( rval, "Error in adjacencies_iterate" );
00176 
00177         for( int v = 0; v < count; v++ )
00178         {
00179             const vector< EntityHandle >* avec = *( adjs_ptr + v );
00180             for( vector< EntityHandle >::const_iterator ait = avec->begin(); ait != avec->end(); ++ait )
00181             {
00182                 // Get chunk that this element resides in; upper_bound points to the first element
00183                 // strictly > key, so get that and decrement (would work the same as lower_bound
00184                 // with an if-test and decrement)
00185                 map< EntityHandle, tag_struct >::iterator mit = elem_map.upper_bound( *ait );
00186                 --mit;
00187                 // Index of *ait in that chunk
00188                 int a_ind     = *ait - ( *mit ).first;
00189                 tag_struct ts = ( *mit ).second;
00190                 ts.avg_ptr[3 * a_ind + 0] += x_ptr[v];  // Tag on each element is 3 doubles, x/y/z
00191                 ts.avg_ptr[3 * a_ind + 1] += y_ptr[v];
00192                 ts.avg_ptr[3 * a_ind + 2] += z_ptr[v];
00193                 ts.nv_ptr[a_ind]++;  // Increment the vertex count
00194             }
00195         }
00196 
00197         v_it += count;
00198     }
00199 
00200     // Normalize tag2 by vertex count; loop over elements using same approach as before
00201     // At the same time, compare values of tag1 and tag2
00202     e_it = elems.begin();
00203     while( e_it != elems.end() )
00204     {
00205         // Get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers
00206         // for all verts
00207         rval = mbImpl->tag_iterate( tag1, e_it, elems.end(), count, (void*&)tag1_ptr );MB_CHK_SET_ERR( rval, "Error in tag1_iterate" );
00208         rval = mbImpl->tag_iterate( tag2, e_it, elems.end(), count, (void*&)tag2_ptr );MB_CHK_SET_ERR( rval, "Error in tag2_iterate" );
00209         rval = mbImpl->tag_iterate( tag3, e_it, elems.end(), count, (void*&)tag3_ptr );MB_CHK_SET_ERR( rval, "Error in tag3_iterate" );
00210 
00211         // Iterate over elements in this chunk
00212         for( int i = 0; i < count; i++ )
00213         {
00214             for( int j = 0; j < 3; j++ )
00215                 tag2_ptr[3 * i + j] /= (double)tag3_ptr[i];  // Normalize by # verts
00216             if( tag1_ptr[3 * i] != tag2_ptr[3 * i] || tag1_ptr[3 * i + 1] != tag2_ptr[3 * i + 1] ||
00217                 tag1_ptr[3 * i + 2] != tag2_ptr[3 * i + 2] )
00218                 cout << "Tag1, tag2 disagree for element " << *e_it + i << endl;
00219         }
00220 
00221         e_it += count;
00222     }
00223 
00224     // Ok, we're done, shut down MOAB
00225     delete mbImpl;
00226 
00227     return 0;
00228 }
00229 
00230 ErrorCode create_mesh_with_holes( Interface* mbImpl, int nquads, int nholes )
00231 {
00232     // First make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are
00233     // numbered in layers
00234     ReadUtilIface* read_iface;
00235     ErrorCode rval = mbImpl->query_interface( read_iface );MB_CHK_SET_ERR( rval, "Error in query_interface" );
00236     vector< double* > coords;
00237     EntityHandle start_vert, start_elem, *connect;
00238     // Create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop
00239     // over elems later
00240     rval = read_iface->get_node_coords( 3, 2 * ( nquads + 1 ), 0, start_vert, coords );MB_CHK_SET_ERR( rval, "Error in get_node_arrays" );
00241     // Create elems
00242     rval = read_iface->get_element_connect( nquads, 4, MBQUAD, 0, start_elem, connect );MB_CHK_SET_ERR( rval, "Error in get_element_connect" );
00243     for( int i = 0; i < nquads; i++ )
00244     {
00245         coords[0][2 * i] = coords[0][2 * i + 1] = (double)i;  // x values are all i
00246         coords[1][2 * i]                        = 0.0;
00247         coords[1][2 * i + 1]                    = 1.0;          // y coords
00248         coords[2][2 * i] = coords[2][2 * i + 1] = (double)0.0;  // z values, all zero (2d mesh)
00249         EntityHandle quad_v                     = start_vert + 2 * i;
00250         for( int j = 0; j < 4; j++ )
00251             connect[4 * i + j] = quad_v + j;  // Connectivity of each quad is a sequence starting from quad_v
00252     }
00253     // Last two vertices
00254     // Cppcheck warning (false positive): variable coords is assigned a value that is never used
00255     coords[0][2 * nquads] = coords[0][2 * nquads + 1] = (double)nquads;
00256     coords[1][2 * nquads]                             = 0.0;
00257     coords[1][2 * nquads + 1]                         = 1.0;          // y coords
00258     coords[2][2 * nquads] = coords[2][2 * nquads + 1] = (double)0.0;  // z values, all zero (2d mesh)
00259 
00260     // Now delete nholes elements, spaced approximately equally through mesh, so contiguous size is
00261     // about nquads/(nholes + 1) reinterpret start_elem as the next element to be deleted
00262     int de = nquads / ( nholes + 1 );
00263     for( int i = 0; i < nholes; i++ )
00264     {
00265         start_elem += de;
00266         rval = mbImpl->delete_entities( &start_elem, 1 );MB_CHK_SET_ERR( rval, "Error in delete_entities" );
00267     }
00268 
00269     return MB_SUCCESS;
00270 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines