moab
DirectAccessWithHoles.cpp
Go to the documentation of this file.
00001 
00032 #include "moab/Core.hpp"
00033 #include "moab/ProgOptions.hpp"
00034 #include "moab/ReadUtilIface.hpp"
00035 #include <map>
00036 #include <iostream>
00037 #include <assert.h>
00038 
00039 // Error routines for use with MOAB API
00040 #define CHKERR(CODE, MSG) do {if (MB_SUCCESS != (CODE)) {std::string errstr;  mbImpl->get_last_error(errstr);   \
00041         std::cerr << errstr << std::endl; std::cerr << MSG << std::endl; return CODE;}} while(false)
00042 
00043 using namespace moab;
00044 
00045 ErrorCode create_mesh_with_holes(Interface *mbImpl, int nquads, int nholes);
00046 
00047 struct tag_struct {double *avg_ptr; int *nv_ptr;};
00048 
00049 int main(int argc, char **argv)
00050 {
00051     // get MOAB instance
00052   Interface *mbImpl = new Core;
00053   if (NULL == mbImpl) return 1;
00054 
00055   int nquads = 1000, nholes = 1;
00056   
00057     // parse options
00058   ProgOptions opts;
00059   opts.addOpt<int>(std::string("nquads,n"), std::string("Number of quads in the mesh (default = 1000"), &nquads);
00060   opts.addOpt<int>(std::string("holes,H"), std::string("Number of holes in the element handle space (default = 1"), &nholes);
00061   opts.parseCommandLine(argc, argv);
00062   if (nholes >= nquads) {
00063     std::cerr << "Number of holes needs to be < number of elements." << std::endl;
00064     return 1;
00065   }
00066 
00067     // create simple structured mesh with hole, but using unstructured representation
00068   ErrorCode rval = create_mesh_with_holes(mbImpl, nquads, nholes); CHKERR(rval, "Trouble creating mesh.");
00069   
00070     // get all vertices and non-vertex entities
00071   Range verts, elems;
00072   rval = mbImpl->get_entities_by_handle(0, elems); CHKERR(rval, "Getting all entities.");
00073   verts = elems.subset_by_dimension(0);
00074   elems -= verts;
00075 
00076     // create tag1 (element-based avg), tag2 (vertex-based avg), tag3 (# connected verts)
00077   Tag tag1, tag2, tag3;
00078   rval = mbImpl->tag_get_handle("tag1", 3, MB_TYPE_DOUBLE, tag1, MB_TAG_DENSE | MB_TAG_CREAT); CHKERR(rval, "Creating tag1.");
00079   double def_val[3] = {0.0, 0.0, 0.0}; // need a default value for tag2 because we sum into it
00080   rval = mbImpl->tag_get_handle("tag2", 3, MB_TYPE_DOUBLE, tag2, MB_TAG_DENSE | MB_TAG_CREAT, def_val); CHKERR(rval, "Creating tag2.");
00081   int def_val_int = 0;  // need a default value for tag3 because we increment it
00082   rval = mbImpl->tag_get_handle("tag3", 1, MB_TYPE_INTEGER, tag3, MB_TAG_DENSE | MB_TAG_CREAT, &def_val_int); CHKERR(rval, "Creating tag3.");
00083   
00084     // Get connectivity, coordinate, tag, and adjacency iterators
00085   EntityHandle *conn_ptr;
00086   double *x_ptr, *y_ptr, *z_ptr, *tag1_ptr, *tag2_ptr;
00087   int *tag3_ptr;
00088   
00089     // First vertex is at start of range (ranges are sorted), and is offset for vertex index calculation
00090   EntityHandle first_vert = *verts.begin();
00091 
00092     // When iterating over elements, each chunk can have a different # vertices; also, count tells you how many
00093     // elements are in the current chunk
00094   int vpere, count;
00095   
00096     // Get coordinates iterator, just need this once because we know verts handle space doesn't have holes
00097   rval = mbImpl->coords_iterate(verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count); CHKERR(rval, "coords_iterate.");
00098   assert(count == (int) verts.size()); // should end up with just one contiguous chunk of vertices
00099 
00100     // Iterate through elements, computing midpoint based on vertex positions, set on element-based tag1
00101     // Control loop by iterator over elem range
00102   Range::iterator e_it = elems.begin();
00103 
00104   while (e_it != elems.end()) {
00105       // get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers for all verts
00106     rval = mbImpl->connect_iterate(e_it, elems.end(), conn_ptr, vpere, count); CHKERR(rval, "connect_iterate.");
00107     rval = mbImpl->tag_iterate(tag1, e_it, elems.end(), count, (void*&)tag1_ptr); CHKERR(rval, "tag1_iterate.");
00108 
00109       // iterate over elements in this chunk 
00110     for (int i = 0; i < count; i++) {
00111       tag1_ptr[0] = tag1_ptr[1] = tag1_ptr[2] = 0.0; // initialize position for this element
00112       for (int j = 0; j < vpere; j++) { // loop over vertices in this element
00113         int v_index = conn_ptr[j] - first_vert; // vert index is just the offset from first vertex
00114         tag1_ptr[0] += x_ptr[v_index];
00115         tag1_ptr[1] += y_ptr[v_index]; // sum vertex positions into tag1...
00116         tag1_ptr[2] += z_ptr[v_index];
00117       }
00118       tag1_ptr[0] /= vpere;
00119       tag1_ptr[1] /= vpere; // then normalize
00120       tag1_ptr[2] /= vpere;
00121       
00122         // done with this element; advance connect_ptr and tag1_ptr to next element
00123       conn_ptr += vpere;
00124       tag1_ptr += 3;
00125     } // loop over elements in chunk
00126     
00127       // done with chunk; advance range iterator by count; will skip over gaps in range
00128     e_it += count;
00129   } // while loop over all elements
00130   
00131     // Iterate through vertices, summing positions into tag2 on connected elements and incrementing vertex count
00132     // Iterate over chunks the same as elements, even though we know we have only one chunk here, just to show
00133     // how it's done
00134 
00135     // Create a std::map from EntityHandle (first entity handle in chunk) to 
00136     // tag_struct (ptrs to start of avg/#verts tags for that chunk); then for a given entity handle, we can quickly
00137     // find the chunk it's in using map::lower_bound; could have set up this map in earlier loop over elements, but do
00138     // it here for clarity
00139   
00140   std::map< EntityHandle, tag_struct> elem_map;
00141   e_it = elems.begin();
00142   while (e_it != elems.end()) {
00143     tag_struct ts = {NULL, NULL};
00144     rval = mbImpl->tag_iterate(tag2, e_it, elems.end(), count, (void*&)ts.avg_ptr); CHKERR(rval, "tag2_iterate.");
00145     rval = mbImpl->tag_iterate(tag3, e_it, elems.end(), count, (void*&)ts.nv_ptr); CHKERR(rval, "tag3_iterate.");
00146     elem_map[*e_it] = ts;
00147     e_it += count;
00148   }
00149 
00150     // call a vertex-quad adjacencies function to generate vertex-element adjacencies in MOAB
00151   Range::iterator v_it = verts.begin();
00152   Range dum_range;
00153   rval = mbImpl->get_adjacencies(&(*v_it), 1, 2, false, dum_range); CHKERR(rval, "get_adjacencies");
00154   const std::vector<EntityHandle> **adjs_ptr;
00155   while (v_it != verts.end()) {
00156       // get coords ptrs, adjs_ptr; can't set tag2_ptr by direct access, because of hole in element handle space
00157     rval = mbImpl->coords_iterate(v_it, verts.end(), x_ptr, y_ptr, z_ptr, count); CHKERR(rval, "coords_iterate.");
00158     rval = mbImpl->adjacencies_iterate(v_it, verts.end(), adjs_ptr, count); CHKERR(rval, "adjacencies_iterate.");
00159     
00160     for (int v = 0; v < count; v++) {
00161       const std::vector<EntityHandle> *avec = *(adjs_ptr+v);
00162       for (std::vector<EntityHandle>::const_iterator ait = avec->begin(); ait != avec->end(); ait++) {
00163           // get chunk that this element resides in; upper_bound points to the first element strictly > key, so get that and decrement
00164           // (would work the same as lower_bound with an if-test and decrement)
00165         std::map<EntityHandle, tag_struct>::iterator mit = elem_map.upper_bound(*ait); mit--;
00166           // index of *ait in that chunk
00167         int a_ind = *ait - (*mit).first;
00168         tag_struct ts = (*mit).second;
00169         ts.avg_ptr[3*a_ind]   += x_ptr[v];   // tag on each element is 3 doubles, x/y/z
00170         ts.avg_ptr[3*a_ind+1] += y_ptr[v];
00171         ts.avg_ptr[3*a_ind+2] += z_ptr[v];
00172         ts.nv_ptr[a_ind]++;  // increment the vertex count
00173       }
00174     }
00175 
00176     v_it += count;
00177   }
00178         
00179     // Normalize tag2 by vertex count; loop over elements using same approach as before
00180     // At the same time, compare values of tag1 and tag2
00181   e_it = elems.begin();
00182   while (e_it != elems.end()) {
00183       // get conn_ptr, tag1_ptr for next contiguous chunk of element handles, and coords pointers for all verts
00184     rval = mbImpl->tag_iterate(tag1, e_it, elems.end(), count, (void*&)tag1_ptr); CHKERR(rval, "tag1_iterate.");
00185     rval = mbImpl->tag_iterate(tag2, e_it, elems.end(), count, (void*&)tag2_ptr); CHKERR(rval, "tag2_iterate.");
00186     rval = mbImpl->tag_iterate(tag3, e_it, elems.end(), count, (void*&)tag3_ptr); CHKERR(rval, "tag3_iterate.");
00187 
00188       // iterate over elements in this chunk 
00189     for (int i = 0; i < count; i++) {
00190       for (int j = 0; j < 3; j++) tag2_ptr[3*i+j] /= (double)tag3_ptr[i];  // normalize by # verts
00191       if (tag1_ptr[3*i] != tag2_ptr[3*i] || tag1_ptr[3*i+1] != tag2_ptr[3*i+1] || tag1_ptr[3*i+2] != tag2_ptr[3*i+2]) 
00192         std::cout << "Tag1, tag2 disagree for element " << *e_it + i << std::endl;
00193     }
00194 
00195     e_it += count;
00196   }
00197 
00198     // Ok, we're done, shut down MOAB
00199   delete mbImpl;
00200 
00201   return 0;
00202 }
00203 
00204 ErrorCode create_mesh_with_holes(Interface *mbImpl, int nquads, int nholes) 
00205 {
00206     // first make the mesh, a 1d array of quads with left hand side x = elem_num; vertices are numbered in layers
00207   ReadUtilIface *read_iface;
00208   ErrorCode rval = mbImpl->query_interface(read_iface); CHKERR(rval, "query_interface");
00209   std::vector<double *> coords;
00210   EntityHandle start_vert, start_elem, *connect;
00211     // create verts, num is 4(nquads+1) because they're in a 1d row; will initialize coords in loop over elems later
00212   rval = read_iface->get_node_coords (3, 2*(nquads+1), 0, start_vert, coords); CHKERR(rval, "get_node_arrays");
00213     // create elems
00214   rval = read_iface->get_element_connect(nquads, 4, MBQUAD, 0, start_elem, connect); CHKERR(rval, "get_element_connect");
00215   for (int i = 0; i < nquads; i++) {
00216     coords[0][2*i] = coords[0][2*i+1] = (double) i; // x values are all i
00217     coords[1][2*i] = 0.0; coords[1][2*i+1] = 1.0; // y coords
00218     coords[2][2*i] = coords[2][2*i+1] = (double) 0.0; // z values, all zero (2d mesh)
00219     EntityHandle quad_v = start_vert + 2*i;
00220     for (int j = 0; j < 4; j++) connect[4*i+j] = quad_v+j; // connectivity of each quad is a sequence starting from quad_v
00221   }
00222     // last two vertices
00223   coords[0][2*nquads] = coords[0][2*nquads+1] = (double) nquads;
00224   coords[1][2*nquads] = 0.0; coords[1][2*nquads+1] = 1.0; // y coords
00225   coords[2][2*nquads] = coords[2][2*nquads+1] = (double) 0.0; // z values, all zero (2d mesh)
00226   
00227     // now delete nholes elements, spaced approximately equally through mesh, so contiguous size is about nquads/(nholes+1)
00228     // reinterpret start_elem as the next element to be deleted
00229   int de = nquads / (nholes + 1);
00230   for (int i = 0; i < nholes; i++) {
00231     start_elem += de;
00232     rval = mbImpl->delete_entities(&start_elem, 1); CHKERR(rval, "delete_entities");
00233   }
00234   
00235   return MB_SUCCESS;
00236 }
00237 
00238     
00239   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines