Branch data Line data Source code
1 : : #include "meshkit/CopyMesh.hpp"
2 : : #include "meshkit/MKCore.hpp"
3 : : #include "meshkit/ModelEnt.hpp"
4 : : #include "meshkit/SizingFunction.hpp"
5 : : #include "meshkit/RegisterMeshOp.hpp"
6 : : #include "meshkit/LocalSet.hpp"
7 : :
8 : : #include "iMesh_extensions.h"
9 : : #include "MBCN.h"
10 : :
11 : : #define CHKERR(err) do { \
12 : : if ((err) != iBase_SUCCESS) \
13 : : return iBase_ErrorType(err); \
14 : : } while(false)
15 : :
16 : :
17 : : namespace MeshKit
18 : : {
19 : :
20 : : // static registration of this mesh scheme
21 : : moab::EntityType CopyMesh_tps[] = { moab::MBVERTEX,
22 : : moab::MBEDGE,
23 : : moab::MBTRI,
24 : : moab::MBHEX,
25 : : moab::MBMAXTYPE};
26 : 40 : const moab::EntityType* CopyMesh::output_types()
27 : 40 : { return CopyMesh_tps; }
28 : :
29 : 4 : CopyMesh::CopyMesh(MKCore *mkcore, const MEntVector &me_vec)
30 : : : MeshScheme(mkcore, me_vec),
31 [ + - ]: 4 : mesh(mkcore->imesh_instance()),
32 : : copyTag(mkcore, "__CopyMeshTag"),
33 : 0 : transform(new Copy::Identity()),
34 : : copySets(mkcore),
35 [ + - ][ + - ]: 8 : expandSets(mkcore)
[ + - ][ + - ]
[ + - ][ + - ]
36 : : {
37 : 4 : flag_process_ce_set = false;
38 : 4 : }
39 : :
40 : 12 : CopyMesh::~CopyMesh()
41 : : {
42 [ + - ]: 4 : delete transform;
43 [ - + ]: 8 : }
44 : :
45 : :
46 : 0 : bool CopyMesh::add_modelent(ModelEnt *model_ent)
47 : : {
48 : 0 : return MeshOp::add_modelent(model_ent);
49 : : }
50 : :
51 : 4 : void CopyMesh::setup_this()
52 : : {
53 : 4 : }
54 : :
55 : 4 : void CopyMesh::execute_this()
56 : : {
57 : 4 : iBase_EntitySetHandle t = NULL;
58 [ + - + - ]: 16 : for (MEntSelection::iterator mit = mentSelection.begin();
[ + + ]
59 : 8 : mit != mentSelection.end(); mit++) {
60 [ + - ]: 4 : ModelEnt *me = mit->first;
61 : : //orig_ents[i++] = reinterpret_cast<iBase_EntityHandle> (me->mesh_handle());
62 [ + - ]: 4 : t = reinterpret_cast<iBase_EntitySetHandle> (me->mesh_handle());
63 : : }
64 : :
65 [ + - ][ + - ]: 4 : LocalSet set(this->mk_core());
66 [ + - ]: 8 : std::vector<iBase_EntityHandle> original;
67 : 4 : original.clear();
68 : : iBase_EntityType type_t;
69 [ + - ][ + - ]: 4 : IBERRCHK(mesh->getEntType((iBase_EntityHandle)t, type_t), *mesh);
70 : : // check if this is a set(4)
71 [ - + ]: 4 : if((int) type_t !=4){
72 [ # # ][ # # ]: 0 : std::cout << "Invalid model ent set, bailing out.." << std::endl;
73 : 0 : exit(0);
74 : : }
75 : :
76 [ + - ][ + - ]: 4 : IBERRCHK(mesh->getEntities(t, iBase_ALL_TYPES, iMesh_ALL_TOPOLOGIES, original), *mesh);
77 [ + - ][ + - ]: 4 : IBERRCHK(mesh->addEntArrToSet(&original[0], original.size(), set), *mesh);
[ + - ][ + - ]
78 [ + - ][ + - ]: 8 : do_copy(set);
79 : 4 : }
80 : :
81 : 4 : int CopyMesh::getStructure(iMesh_Instance instance,
82 : : iBase_EntitySetHandle set,
83 : : std::vector<iBase_EntityHandle> &ents,
84 : : std::vector<iBase_EntityHandle> &unique_adj,
85 : : std::vector<int> &indices,
86 : : std::vector<int> &offsets)
87 : : {
88 : : // 1) Get source entities, making sure verts are first
89 : : int num;
90 : : int err;
91 [ + - ]: 4 : iMesh_getNumOfTypeRec(instance, set, iBase_ALL_TYPES, true, &num, &err);
92 [ - + ]: 4 : CHKERR(err);
93 : :
94 [ + - ]: 4 : ents.resize(num);
95 [ + - ]: 4 : offsets.resize(num+1);
96 : :
97 [ + - ]: 4 : iBase_EntityHandle *block = &ents[0];
98 : 4 : int block_alloc = ents.size(), block_size, num_verts = 0;
99 [ + - ][ + + ]: 33 : for (int t = iMesh_POINT; t < iMesh_ALL_TOPOLOGIES && block_alloc; ++t) {
100 : : iMesh_getEntitiesRec(instance, set, iBase_ALL_TYPES, t, true,
101 [ + - ]: 29 : &block, &block_alloc, &block_size, &err);
102 [ - + ]: 29 : CHKERR(err);
103 : :
104 : 29 : block_alloc -= block_size;
105 : 29 : block += block_size;
106 [ + + ]: 29 : if (t == iMesh_POINT)
107 : 4 : num_verts = block_size;
108 : : }
109 : :
110 : : // 2) Get verts adjacent to all source entitites (verts are adj to themselves)
111 [ + - ][ + - ]: 4 : std::vector<iBase_EntityHandle> all_adj(ents.begin(), ents.begin()+num_verts);
112 : :
113 : : // first, fill the vertex-vertex adjacencies
114 [ + + ]: 85 : for (int i = 0; i < num_verts; ++i)
115 [ + - ]: 81 : offsets[i] = i;
116 : :
117 : 4 : iBase_EntityHandle *tmp_adj = NULL;
118 : 4 : int tmp_adj_alloc = 0, tmp_adj_size;
119 [ + - ]: 4 : int *tmp_off = &offsets[num_verts];
120 : 4 : int tmp_off_alloc = offsets.size() - num_verts, tmp_off_size;
121 [ + - ]: 4 : iMesh_getEntArrAdj(instance, &ents[num_verts], ents.size()-num_verts,
122 : : iBase_VERTEX, &tmp_adj, &tmp_adj_alloc, &tmp_adj_size,
123 [ + - ]: 4 : &tmp_off, &tmp_off_alloc, &tmp_off_size, &err);
124 [ - + ]: 4 : CHKERR(err);
125 : :
126 : : // shift all the offsets to account for vertices
127 [ + + ]: 45 : for(unsigned int i = num_verts; i < offsets.size(); ++i)
128 [ + - ]: 41 : offsets[i] += num_verts;
129 : :
130 [ + - ]: 4 : all_adj.reserve(all_adj.size() + tmp_adj_size);
131 [ + - ]: 4 : all_adj.insert(all_adj.end(), tmp_adj, tmp_adj+tmp_adj_size);
132 : 4 : free(tmp_adj);
133 : :
134 : : // 3) Get unique adjacent vertices and offsets
135 [ + - ]: 4 : unique_adj.resize(all_adj.size());
136 [ + - ]: 4 : indices.resize(all_adj.size());
137 [ + - ]: 4 : std::copy(all_adj.begin(), all_adj.end(), unique_adj.begin());
138 [ + - ]: 4 : std::sort(unique_adj.begin(), unique_adj.end());
139 : :
140 : : size_t unique_size;
141 [ + - ][ + - ]: 4 : unique_size = std::unique(unique_adj.begin(), unique_adj.end()) -
142 : 4 : unique_adj.begin();
143 [ + - ]: 4 : unique_adj.resize(unique_size);
144 : :
145 [ + + ]: 329 : for (size_t i = 0; i < all_adj.size(); ++i) {
146 [ + - ]: 325 : indices[i] = std::lower_bound(unique_adj.begin(), unique_adj.end(),
147 [ + - ][ + - ]: 325 : all_adj[i]) - unique_adj.begin();
[ + - ]
148 : : }
149 : :
150 : 4 : return 0;
151 : : }
152 : :
153 : 4 : void CopyMesh::do_copy(iMesh::EntitySetHandle set_handle)
154 : : {
155 [ - + ]: 4 : assert(transform);
156 : :
157 [ + - ][ + - ]: 4 : LocalTag local_tag(this->mk_core());
158 : :
159 [ + - ]: 8 : std::vector<iBase_EntityHandle> ents;
160 [ + - ]: 8 : std::vector<iBase_EntityHandle> verts;
161 [ + - ]: 8 : std::vector<int> indices;
162 [ + - ]: 8 : std::vector<int> offsets;
163 : : // IBERRCHK(iMesh_getStructure(mesh->instance(), set_handle, ents, verts,
164 : : // indices, offsets), *mesh);
165 : : getStructure(mesh->instance(), set_handle, ents, verts,
166 [ + - ][ + - ]: 4 : indices, offsets);
167 : : // copy the vertices
168 [ + - ]: 8 : std::vector<iBase_EntityHandle> new_verts;
169 [ + - ]: 4 : transform->transform(mesh, verts, new_verts);
170 [ - + ]: 4 : assert(new_verts.size() == verts.size());
171 : :
172 : : // set the local copy tags on vertices
173 : : // XXX: Should this really happen? Doing so adds more entities to copy sets
174 : : // than explicitly passed into this function. This may be a domain-specific
175 : : // question.
176 [ + - ][ + - ]: 4 : IBERRCHK(mesh->setEHArrData(&verts[0], verts.size(), local_tag,
[ + - ][ + - ]
177 [ + - ]: 4 : &new_verts[0]), *mesh);
178 : :
179 : : // now connect the new vertices to make the higher-dimension entities
180 [ + - ][ + - ]: 4 : connect_the_dots(mesh, local_tag, ents, indices, offsets, new_verts);
181 : :
182 : : // take care of copy/expand sets
183 [ + - ]: 4 : update_sets();
184 : :
185 [ + - ][ + - ]: 4 : link_expand_sets(expandSets, local_tag);
186 : :
187 [ + + ]: 4 : if(flag_process_ce_set == true)
188 [ + - ][ + - ]: 1 : process_ce_sets(mesh, copySets.sets(), local_tag);
[ + - ]
189 [ + - ][ + - ]: 4 : process_ce_sets(mesh, expandSets.sets(), local_tag);
[ + - ]
190 : :
191 [ + - ][ + - ]: 8 : tag_copy_sets(copySets, local_tag, copyTag);
[ + - ]
192 : 4 : }
193 : :
194 : 4 : void CopyMesh::update_sets()
195 : : {
196 : 4 : copySets.update_tagged_sets();
197 : 4 : expandSets.update_tagged_sets();
198 : 4 : }
199 : :
200 : 0 : void CopyMesh::tag_copied_sets(const char **tag_names, const char **tag_vals,
201 : : const int num_tags)
202 : : {
203 [ # # ]: 0 : for (int t = 0; t < num_tags; t++) {
204 : : iMesh::TagHandle tag;
205 [ # # ][ # # ]: 0 : IBERRCHK(mesh->getTagHandle(tag_names[t], tag), *mesh);
206 : :
207 [ # # ]: 0 : tag_copy_sets(mesh, copyTag, copySets.sets(), tag,
208 [ # # ][ # # ]: 0 : tag_vals ? tag_vals[t] : NULL);
[ # # ]
209 : : }
210 : 0 : }
211 : :
212 : 0 : void CopyMesh::tag_copied_sets(iMesh::TagHandle *tags, const char **tag_vals,
213 : : const int num_tags)
214 : : {
215 [ # # ]: 0 : for (int t = 0; t < num_tags; t++)
216 : 0 : tag_copy_sets(mesh, copyTag, copySets.sets(), tags[t],
217 [ # # ]: 0 : tag_vals ? tag_vals[t] : NULL);
218 : 0 : }
219 : :
220 : 7 : void connect_the_dots(iMesh *mesh, iBase_TagHandle local_tag,
221 : : const std::vector<iBase_EntityHandle> &ents,
222 : : const std::vector<int> &indices,
223 : : const std::vector<int> &offsets,
224 : : const std::vector<iBase_EntityHandle> &verts)
225 : : {
226 [ + - ]: 7 : std::vector<iMesh_EntityTopology> topos(ents.size());
227 [ + - ][ + - ]: 7 : IBERRCHK(mesh->getEntArrTopo(&ents[0], ents.size(), &topos[0]), *mesh);
[ + - ][ + - ]
228 : :
229 : : // scan forward to first non-vertex
230 : 7 : size_t pos = 0;
231 [ + - ][ + - ]: 88 : while (pos < topos.size() && iMesh_POINT == topos[pos])
[ + + ][ + + ]
232 : 81 : pos++;
233 [ - + ]: 14 : if (pos == topos.size()) return;
234 : :
235 : : // for each run of same size & type
236 [ + - ][ + - ]: 14 : std::vector<iBase_EntityHandle> connect, new_ents;
[ + - ]
237 : 7 : size_t begin, end = pos;
238 [ + + ]: 17 : while (end < ents.size()) {
239 : : // get next run; end points to start of *next* element,
240 : : // or ents_size if no elems left
241 : 10 : begin = end++;
242 : :
243 [ + - ]: 10 : iMesh_EntityTopology topo = topos[begin];
244 [ + - ][ + - ]: 10 : int vtx_per_ent = offsets[end] - offsets[begin];
245 [ + + ][ + + ]: 116 : while (end < ents.size() &&
246 [ + + ][ + - ]: 75 : topos[end] == topo &&
[ + - ]
247 [ + - ][ + - ]: 31 : offsets[end+1] - offsets[end] == vtx_per_ent)
248 : 31 : end++;
249 : 10 : size_t num_ents = end - begin;
250 : :
251 : : int mbcn_type;
252 : : int num_corner_verts;
253 [ + - ]: 10 : iMesh_MBCNType(topo, &mbcn_type);
254 [ + - ]: 10 : MBCN_VerticesPerEntity(mbcn_type, &num_corner_verts);
255 : :
256 : : // build vector of vtx handles
257 [ + - ]: 10 : connect.resize(vtx_per_ent * num_ents);
258 [ + + ]: 269 : for (size_t i = 0; i < connect.size(); i++)
259 [ + - ][ + - ]: 259 : connect[i] = verts[indices[offsets[begin] + i]];
[ + - ][ + - ]
260 : :
261 : : // create entities
262 [ + - ]: 10 : new_ents.resize(num_ents);
263 : :
264 [ + - ]: 10 : if (num_corner_verts == vtx_per_ent) {
265 [ + - ][ + - ]: 10 : IBERRCHK(mesh->createEntArr(topo, &connect[0], connect.size(),
[ + - ]
266 [ + - ]: 10 : &new_ents[0]), *mesh);
267 : : }
268 : : else {
269 : : // use single-entity function in this case, entity might have higher-
270 : : // order nodes (imesh fcn doesn't have argument for # entities)
271 [ # # ]: 0 : for (size_t i = 0; i < num_ents; i++) {
272 [ # # ][ # # ]: 0 : IBERRCHK(mesh->createEnt(topo, &connect[i*vtx_per_ent],
[ # # ]
273 [ # # ]: 0 : vtx_per_ent, new_ents[i]), *mesh);
274 : : }
275 : : }
276 : :
277 : : // set the local copy tags
278 [ + - ][ + - ]: 10 : IBERRCHK(mesh->setEHArrData(&ents[begin], num_ents, local_tag,
[ + - ]
279 [ + - ]: 10 : &new_ents[0]), *mesh);
280 : 7 : }
281 : : }
282 : :
283 [ + - ][ + - ]: 156 : } // namespace MeshKit
|