moab
|
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