MeshKit  1.0
CopyMesh.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines