MeshKit
1.0
|
00001 #include "meshkit/CopyMesh.hpp" 00002 #include "meshkit/MKCore.hpp" 00003 #include "meshkit/ModelEnt.hpp" 00004 #include "meshkit/SizingFunction.hpp" 00005 #include "meshkit/RegisterMeshOp.hpp" 00006 #include "meshkit/LocalSet.hpp" 00007 00008 #include "iMesh_extensions.h" 00009 #include "MBCN.h" 00010 00011 #define CHKERR(err) do { \ 00012 if ((err) != iBase_SUCCESS) \ 00013 return iBase_ErrorType(err); \ 00014 } while(false) 00015 00016 00017 namespace MeshKit 00018 { 00019 00020 // static registration of this mesh scheme 00021 moab::EntityType CopyMesh_tps[] = { moab::MBVERTEX, 00022 moab::MBEDGE, 00023 moab::MBTRI, 00024 moab::MBHEX, 00025 moab::MBMAXTYPE}; 00026 const moab::EntityType* CopyMesh::output_types() 00027 { return CopyMesh_tps; } 00028 00029 CopyMesh::CopyMesh(MKCore *mkcore, const MEntVector &me_vec) 00030 : MeshScheme(mkcore, me_vec), 00031 mesh(mkcore->imesh_instance()), 00032 copyTag(mkcore, "__CopyMeshTag"), 00033 transform(new Copy::Identity()), 00034 copySets(mkcore), 00035 expandSets(mkcore) 00036 { 00037 flag_process_ce_set = false; 00038 } 00039 00040 CopyMesh::~CopyMesh() 00041 { 00042 delete transform; 00043 } 00044 00045 00046 bool CopyMesh::add_modelent(ModelEnt *model_ent) 00047 { 00048 return MeshOp::add_modelent(model_ent); 00049 } 00050 00051 void CopyMesh::setup_this() 00052 { 00053 } 00054 00055 void CopyMesh::execute_this() 00056 { 00057 iBase_EntitySetHandle t = NULL; 00058 for (MEntSelection::iterator mit = mentSelection.begin(); 00059 mit != mentSelection.end(); mit++) { 00060 ModelEnt *me = mit->first; 00061 //orig_ents[i++] = reinterpret_cast<iBase_EntityHandle> (me->mesh_handle()); 00062 t = reinterpret_cast<iBase_EntitySetHandle> (me->mesh_handle()); 00063 } 00064 00065 LocalSet set(this->mk_core()); 00066 std::vector<iBase_EntityHandle> original; 00067 original.clear(); 00068 iBase_EntityType type_t; 00069 IBERRCHK(mesh->getEntType((iBase_EntityHandle)t, type_t), *mesh); 00070 // check if this is a set(4) 00071 if((int) type_t !=4){ 00072 std::cout << "Invalid model ent set, bailing out.." << std::endl; 00073 exit(0); 00074 } 00075 00076 IBERRCHK(mesh->getEntities(t, iBase_ALL_TYPES, iMesh_ALL_TOPOLOGIES, original), *mesh); 00077 IBERRCHK(mesh->addEntArrToSet(&original[0], original.size(), set), *mesh); 00078 do_copy(set); 00079 } 00080 00081 int CopyMesh::getStructure(iMesh_Instance instance, 00082 iBase_EntitySetHandle set, 00083 std::vector<iBase_EntityHandle> &ents, 00084 std::vector<iBase_EntityHandle> &unique_adj, 00085 std::vector<int> &indices, 00086 std::vector<int> &offsets) 00087 { 00088 // 1) Get source entities, making sure verts are first 00089 int num; 00090 int err; 00091 iMesh_getNumOfTypeRec(instance, set, iBase_ALL_TYPES, true, &num, &err); 00092 CHKERR(err); 00093 00094 ents.resize(num); 00095 offsets.resize(num+1); 00096 00097 iBase_EntityHandle *block = &ents[0]; 00098 int block_alloc = ents.size(), block_size, num_verts = 0; 00099 for (int t = iMesh_POINT; t < iMesh_ALL_TOPOLOGIES && block_alloc; ++t) { 00100 iMesh_getEntitiesRec(instance, set, iBase_ALL_TYPES, t, true, 00101 &block, &block_alloc, &block_size, &err); 00102 CHKERR(err); 00103 00104 block_alloc -= block_size; 00105 block += block_size; 00106 if (t == iMesh_POINT) 00107 num_verts = block_size; 00108 } 00109 00110 // 2) Get verts adjacent to all source entitites (verts are adj to themselves) 00111 std::vector<iBase_EntityHandle> all_adj(ents.begin(), ents.begin()+num_verts); 00112 00113 // first, fill the vertex-vertex adjacencies 00114 for (int i = 0; i < num_verts; ++i) 00115 offsets[i] = i; 00116 00117 iBase_EntityHandle *tmp_adj = NULL; 00118 int tmp_adj_alloc = 0, tmp_adj_size; 00119 int *tmp_off = &offsets[num_verts]; 00120 int tmp_off_alloc = offsets.size() - num_verts, tmp_off_size; 00121 iMesh_getEntArrAdj(instance, &ents[num_verts], ents.size()-num_verts, 00122 iBase_VERTEX, &tmp_adj, &tmp_adj_alloc, &tmp_adj_size, 00123 &tmp_off, &tmp_off_alloc, &tmp_off_size, &err); 00124 CHKERR(err); 00125 00126 // shift all the offsets to account for vertices 00127 for(unsigned int i = num_verts; i < offsets.size(); ++i) 00128 offsets[i] += num_verts; 00129 00130 all_adj.reserve(all_adj.size() + tmp_adj_size); 00131 all_adj.insert(all_adj.end(), tmp_adj, tmp_adj+tmp_adj_size); 00132 free(tmp_adj); 00133 00134 // 3) Get unique adjacent vertices and offsets 00135 unique_adj.resize(all_adj.size()); 00136 indices.resize(all_adj.size()); 00137 std::copy(all_adj.begin(), all_adj.end(), unique_adj.begin()); 00138 std::sort(unique_adj.begin(), unique_adj.end()); 00139 00140 size_t unique_size; 00141 unique_size = std::unique(unique_adj.begin(), unique_adj.end()) - 00142 unique_adj.begin(); 00143 unique_adj.resize(unique_size); 00144 00145 for (size_t i = 0; i < all_adj.size(); ++i) { 00146 indices[i] = std::lower_bound(unique_adj.begin(), unique_adj.end(), 00147 all_adj[i]) - unique_adj.begin(); 00148 } 00149 00150 return 0; 00151 } 00152 00153 void CopyMesh::do_copy(iMesh::EntitySetHandle set_handle) 00154 { 00155 assert(transform); 00156 00157 LocalTag local_tag(this->mk_core()); 00158 00159 std::vector<iBase_EntityHandle> ents; 00160 std::vector<iBase_EntityHandle> verts; 00161 std::vector<int> indices; 00162 std::vector<int> offsets; 00163 // IBERRCHK(iMesh_getStructure(mesh->instance(), set_handle, ents, verts, 00164 // indices, offsets), *mesh); 00165 getStructure(mesh->instance(), set_handle, ents, verts, 00166 indices, offsets); 00167 // copy the vertices 00168 std::vector<iBase_EntityHandle> new_verts; 00169 transform->transform(mesh, verts, new_verts); 00170 assert(new_verts.size() == verts.size()); 00171 00172 // set the local copy tags on vertices 00173 // XXX: Should this really happen? Doing so adds more entities to copy sets 00174 // than explicitly passed into this function. This may be a domain-specific 00175 // question. 00176 IBERRCHK(mesh->setEHArrData(&verts[0], verts.size(), local_tag, 00177 &new_verts[0]), *mesh); 00178 00179 // now connect the new vertices to make the higher-dimension entities 00180 connect_the_dots(mesh, local_tag, ents, indices, offsets, new_verts); 00181 00182 // take care of copy/expand sets 00183 update_sets(); 00184 00185 link_expand_sets(expandSets, local_tag); 00186 00187 if(flag_process_ce_set == true) 00188 process_ce_sets(mesh, copySets.sets(), local_tag); 00189 process_ce_sets(mesh, expandSets.sets(), local_tag); 00190 00191 tag_copy_sets(copySets, local_tag, copyTag); 00192 } 00193 00194 void CopyMesh::update_sets() 00195 { 00196 copySets.update_tagged_sets(); 00197 expandSets.update_tagged_sets(); 00198 } 00199 00200 void CopyMesh::tag_copied_sets(const char **tag_names, const char **tag_vals, 00201 const int num_tags) 00202 { 00203 for (int t = 0; t < num_tags; t++) { 00204 iMesh::TagHandle tag; 00205 IBERRCHK(mesh->getTagHandle(tag_names[t], tag), *mesh); 00206 00207 tag_copy_sets(mesh, copyTag, copySets.sets(), tag, 00208 tag_vals ? tag_vals[t] : NULL); 00209 } 00210 } 00211 00212 void CopyMesh::tag_copied_sets(iMesh::TagHandle *tags, const char **tag_vals, 00213 const int num_tags) 00214 { 00215 for (int t = 0; t < num_tags; t++) 00216 tag_copy_sets(mesh, copyTag, copySets.sets(), tags[t], 00217 tag_vals ? tag_vals[t] : NULL); 00218 } 00219 00220 void connect_the_dots(iMesh *mesh, iBase_TagHandle local_tag, 00221 const std::vector<iBase_EntityHandle> &ents, 00222 const std::vector<int> &indices, 00223 const std::vector<int> &offsets, 00224 const std::vector<iBase_EntityHandle> &verts) 00225 { 00226 std::vector<iMesh_EntityTopology> topos(ents.size()); 00227 IBERRCHK(mesh->getEntArrTopo(&ents[0], ents.size(), &topos[0]), *mesh); 00228 00229 // scan forward to first non-vertex 00230 size_t pos = 0; 00231 while (pos < topos.size() && iMesh_POINT == topos[pos]) 00232 pos++; 00233 if (pos == topos.size()) return; 00234 00235 // for each run of same size & type 00236 std::vector<iBase_EntityHandle> connect, new_ents; 00237 size_t begin, end = pos; 00238 while (end < ents.size()) { 00239 // get next run; end points to start of *next* element, 00240 // or ents_size if no elems left 00241 begin = end++; 00242 00243 iMesh_EntityTopology topo = topos[begin]; 00244 int vtx_per_ent = offsets[end] - offsets[begin]; 00245 while (end < ents.size() && 00246 topos[end] == topo && 00247 offsets[end+1] - offsets[end] == vtx_per_ent) 00248 end++; 00249 size_t num_ents = end - begin; 00250 00251 int mbcn_type; 00252 int num_corner_verts; 00253 iMesh_MBCNType(topo, &mbcn_type); 00254 MBCN_VerticesPerEntity(mbcn_type, &num_corner_verts); 00255 00256 // build vector of vtx handles 00257 connect.resize(vtx_per_ent * num_ents); 00258 for (size_t i = 0; i < connect.size(); i++) 00259 connect[i] = verts[indices[offsets[begin] + i]]; 00260 00261 // create entities 00262 new_ents.resize(num_ents); 00263 00264 if (num_corner_verts == vtx_per_ent) { 00265 IBERRCHK(mesh->createEntArr(topo, &connect[0], connect.size(), 00266 &new_ents[0]), *mesh); 00267 } 00268 else { 00269 // use single-entity function in this case, entity might have higher- 00270 // order nodes (imesh fcn doesn't have argument for # entities) 00271 for (size_t i = 0; i < num_ents; i++) { 00272 IBERRCHK(mesh->createEnt(topo, &connect[i*vtx_per_ent], 00273 vtx_per_ent, new_ents[i]), *mesh); 00274 } 00275 } 00276 00277 // set the local copy tags 00278 IBERRCHK(mesh->setEHArrData(&ents[begin], num_ents, local_tag, 00279 &new_ents[0]), *mesh); 00280 } 00281 } 00282 00283 } // namespace MeshKit