Branch data Line data Source code
1 : : #include "meshkit/MesquiteOpt.hpp"
2 : : #include "meshkit/ModelEnt.hpp"
3 : : #include "meshkit/iMesh.hpp"
4 : : #include "moab/Skinner.hpp"
5 : : #include "moab/mesquite/MsqIMesh.hpp"
6 : : #include "moab/mesquite/QualityAssessor.hpp"
7 : : #include "moab/mesquite/MsqError.hpp"
8 : : #ifdef HAVE_CGM
9 : : # include "moab/mesquite/MsqIGeom.hpp"
10 : : #endif
11 : : #include "meshkit/FreeSmoothDomain.hpp"
12 : :
13 : : #include "moab/mesquite/ShapeImprover.hpp"
14 : : typedef MESQUITE_NS::ShapeImprover DefaultAlgorithm;
15 : :
16 : :
17 : : #define MSQERRCHK(err) \
18 : : do { \
19 : : if ((err)) { \
20 : : throw Error(MK_FAILURE,"%s:%d: Mesquite error: %s", \
21 : : __FILE__, __LINE__, (err).error_message() ); \
22 : : } \
23 : : } while(false)
24 : :
25 : :
26 : : using namespace MESQUITE_NS;
27 : :
28 : : namespace MeshKit {
29 : :
30 : 2 : MesquiteOpt::MesquiteOpt( MKCore* core, const MEntVector &me_vec )
31 : : : MeshOp(core, me_vec),
32 : : msqAlgo(0),
33 : : fixedBoundary(true),
34 : : haveFixedTag(false),
35 : : createdByteTag(false),
36 : 2 : verboseOutput(false)
37 : 2 : {}
38 : :
39 : 42 : const moab::EntityType* MesquiteOpt::output_types()
40 : : {
41 : : const static moab::EntityType end = moab::MBMAXTYPE;
42 : 42 : return &end;
43 : : }
44 : :
45 : 160 : bool MesquiteOpt::can_mesh( iBase_EntityType dim )
46 : : {
47 : 160 : return dim >= 2;
48 : : }
49 : :
50 : 0 : bool MesquiteOpt::can_mesh( ModelEnt* ent )
51 : : {
52 : 0 : return can_mesh( (iBase_EntityType)ent->dimension() );
53 : : }
54 : :
55 : 20 : iBase_TagHandle MesquiteOpt::get_fixed_tag()
56 : : {
57 [ + + ]: 20 : if (!haveFixedTag)
58 : 2 : set_fixed_tag( "fixed" );
59 : 20 : return fixedTag;
60 : : }
61 : :
62 : 2 : void MesquiteOpt::set_fixed_tag( iBase_TagHandle tag )
63 : : {
64 : : int size;
65 : : iMesh::TagValueType type;
66 [ + - ][ + - ]: 2 : mk_core()->imesh_instance()->getTagSizeValues( tag, size );
[ + - ]
67 [ + - ][ + - ]: 2 : mk_core()->imesh_instance()->getTagType( tag, type );
[ + - ]
68 [ + - ][ - + ]: 2 : if (size != 1 || type != iBase_INTEGER)
69 [ # # ]: 0 : throw Error(MK_WRONG_DIMENSION,"Tag as invalid type or size");
70 : 2 : haveFixedTag = true;
71 : 2 : fixedTag = tag;
72 : 2 : }
73 : :
74 : 2 : void MesquiteOpt::set_fixed_tag( const char* name )
75 : : {
76 : : iBase_TagHandle tag;
77 [ + - ][ + - ]: 2 : iBase_ErrorType err = mk_core()->imesh_instance()->getTagHandle( name, tag );
[ + - ]
78 [ + + ]: 2 : if (iBase_SUCCESS == err) {
79 [ + - ]: 1 : set_fixed_tag(tag);
80 : : }
81 : : else {
82 : : // create though moab so we can make it a dense tag
83 : : moab::Tag t;
84 : : moab::ErrorCode rval;
85 : 1 : int zero = 0;
86 [ + - ][ + - ]: 1 : rval = mk_core()->moab_instance()->tag_get_handle( name,
87 : : 1,
88 : : moab::MB_TYPE_INTEGER,
89 : : t,
90 : : moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,
91 [ + - ]: 1 : &zero );
92 [ - + ][ # # ]: 1 : MBERRCHK(rval,mk_core()->moab_instance());
[ # # ][ # # ]
[ # # ][ # # ]
93 : :
94 [ + - ][ + - ]: 1 : err = mk_core()->imesh_instance()->getTagHandle( name, tag );
[ + - ]
95 [ + - ]: 1 : IBERRCHK(err,"Tag created via Moab not accessable via iMesh");
96 [ + - ]: 1 : set_fixed_tag( tag );
97 : : }
98 : 2 : }
99 : :
100 : 10 : void MesquiteOpt::create_byte_tag()
101 : : {
102 [ + + ]: 10 : if (!createdByteTag) {
103 : : // Create though moab so we can make it a dense tag
104 : : // Don't check error code. We don't care if it already exists
105 : : // and futher, we really aren't responsiblefor creating it anyway.
106 : : // We do it here only so we can make it a dense tag.
107 : : moab::Tag t;
108 : 2 : unsigned char zero = 0;
109 [ + - ][ + - ]: 2 : mk_core()->moab_instance()->tag_get_handle( MESQUITE_NS::VERTEX_BYTE_TAG_NAME,
110 : : 1,
111 : : moab::MB_TYPE_INTEGER,
112 : : t,
113 : : moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,
114 [ + - ]: 2 : &zero );
115 : 2 : createdByteTag = true;
116 : : }
117 : 10 : }
118 : :
119 : 1 : void MesquiteOpt::smooth_with_fixed_boundary()
120 : : {
121 : 1 : fixedBoundary = true;
122 : 1 : }
123 : :
124 : 1 : void MesquiteOpt::smooth_with_free_boundary()
125 : : {
126 : : #ifndef HAVE_CGM
127 : : throw Error(MK_NOT_IMPLEMENTED,"Cannot do free smooth w/out Mesquite iRel support");
128 : : #else
129 : 1 : fixedBoundary = false;
130 : : #endif
131 : 1 : }
132 : :
133 : 5 : void MesquiteOpt::setup_this()
134 : : {
135 : 5 : get_fixed_tag();
136 : 5 : create_byte_tag();
137 : 5 : }
138 : :
139 : 15 : void MesquiteOpt::set_fixed_tag( ModelEnt* ent, int value )
140 : : {
141 [ + - ]: 15 : std::vector<int> fixed_vals;
142 [ + - ]: 15 : iBase_TagHandle fixed = get_fixed_tag();
143 [ + - ][ + - ]: 15 : iMesh* mesh = mk_core()->imesh_instance();
144 [ + - ][ + - ]: 30 : std::vector<iBase_EntityHandle> ents, verts;
145 : : iMesh::Error err;
146 : :
147 : 15 : ents.clear();
148 [ + - ]: 15 : err = mesh->getEntities( (iBase_EntitySetHandle)ent->mesh_handle(),
149 [ + - ]: 15 : (iMesh::EntityType)ent->dimension(),
150 : : iMesh_ALL_TOPOLOGIES,
151 [ + - ]: 15 : ents );
152 [ + - ]: 15 : IBERRCHK(err,"Error getting ModelEnt mesh entities via iMesh");
153 : :
154 [ + - ][ + - ]: 15 : if (ent->dimension() > 0) {
155 : 15 : verts.clear();
156 [ + - ]: 15 : fixed_vals.resize(ents.size()+1);
157 [ + - ][ + - ]: 15 : err = mesh->getEntArrAdj( &ents[0], ents.size(), iBase_VERTEX, verts, &fixed_vals[0] );
[ + - ]
158 [ + - ]: 15 : IBERRCHK(err,"Error mesh vertices from mesh entities via iMesh");
159 : : }
160 : : else {
161 : 0 : verts.swap(ents);
162 : : }
163 : :
164 : 15 : fixed_vals.clear();
165 [ + - ]: 15 : fixed_vals.resize( verts.size(), value );
166 [ + - ][ + - ]: 15 : err = mesh->setIntArrData( &verts[0], verts.size(), fixed, &fixed_vals[0] );
[ + - ]
167 [ + - ]: 30 : IBERRCHK(err,"Clearing fixed tag on mesh vertices");
168 : 15 : }
169 : :
170 : 3 : void MesquiteOpt::set_fixed_tag_on_skin( ModelEnt* ent, int value )
171 : : {
172 [ + - ]: 3 : if (ent->dimension() > 0) {
173 : : // if geometric entity, skin is defined by bounding geometry
174 [ + - ]: 3 : if (ent->geom_handle()) {
175 [ + - ]: 3 : MEntVector children;
176 [ + - ][ + - ]: 3 : ent->get_adjacencies( ent->dimension() - 1, children );
177 [ + - ][ + - ]: 15 : for (MEntVector::iterator i = children.begin(); i != children.end(); ++i)
[ + + ]
178 [ + - ][ + - ]: 15 : set_fixed_tag( *i, value );
179 : : }
180 : : // otherwise find the actual skin
181 : : else {
182 [ # # ][ # # ]: 0 : moab::Interface* mb = mk_core()->moab_instance();
183 [ # # ]: 0 : moab::EntityHandle set = static_cast<moab::EntityHandle>( ent->mesh_handle() );
184 : : moab::ErrorCode rval;
185 [ # # ]: 0 : moab::Range elems;
186 [ # # ][ # # ]: 0 : rval = mb->get_entities_by_dimension( set, ent->dimension(), elems );
187 [ # # ][ # # ]: 0 : MBERRCHK(rval, mk_core()->moab_instance());
[ # # ][ # # ]
[ # # ][ # # ]
188 : :
189 [ # # ]: 0 : moab::Range verts;
190 [ # # ]: 0 : moab::Skinner tool(mb);
191 [ # # ]: 0 : moab::ErrorCode err = tool.find_skin( 0, elems, 0, verts );
192 [ # # ][ # # ]: 0 : MBERRCHK(err, mk_core()->moab_instance());
[ # # ][ # # ]
[ # # ][ # # ]
193 : :
194 [ # # ]: 0 : moab::Tag t = reinterpret_cast<moab::Tag>( get_fixed_tag() );
195 [ # # ]: 0 : err = mb->tag_clear_data( t, verts, &value );
196 [ # # ][ # # ]: 3 : MBERRCHK(err, mk_core()->moab_instance());
[ # # ][ # # ]
[ # # ][ # # ]
197 : : }
198 : : }
199 : 3 : }
200 : :
201 : 0 : bool MesquiteOpt::all_model_ents_have_geom() const
202 : : {
203 [ # # ]: 0 : MEntSelection::const_iterator i;
204 [ # # ][ # # ]: 0 : for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
[ # # ]
205 [ # # ]: 0 : ModelEnt* ent = i->first;
206 [ # # ][ # # ]: 0 : if (!ent->geom_handle())
207 : 0 : return false;
208 : : }
209 : 0 : return true;
210 : : }
211 : :
212 : 2 : void MesquiteOpt::get_adjacent_entity_set( MEntSet& from_this,
213 : : MEntVector& ents,
214 : : iBase_EntitySetHandle& result,
215 : : iBase_EntityType& dimension,
216 : : bool& created_result_set )
217 : : {
218 [ - + ]: 2 : if (from_this.empty())
219 [ # # ]: 0 : throw Error(MK_BAD_INPUT,"Input set is empty");
220 : :
221 [ + - ][ + - ]: 2 : iMesh* imesh = mk_core()->imesh_instance();
222 : 2 : bool first = true;
223 : : iBase_ErrorType err;
224 : 2 : created_result_set = false;
225 [ + - ][ + - ]: 4 : MEntVector front, adj, adj2;
[ + - ]
226 [ + - ][ + - ]: 2 : front.push_back(*from_this.begin());
227 [ + - ]: 2 : from_this.erase(from_this.begin());
228 [ + + ]: 4 : while (!front.empty()) {
229 [ + - ]: 2 : ModelEnt* ent = front.back();
230 [ + - ]: 2 : front.pop_back();
231 [ + - ]: 2 : ents.push_back(ent);
232 : :
233 : : try {
234 [ + - ]: 2 : if (first) {
235 [ + - ]: 2 : dimension = (iBase_EntityType)ent->dimension();
236 [ + - ]: 2 : result = (iBase_EntitySetHandle)ent->mesh_handle();
237 : 2 : first = false;
238 : : }
239 : : else {
240 [ # # ][ # # ]: 0 : if (ent->dimension() != dimension)
241 : 0 : dimension = iBase_ALL_TYPES;
242 : :
243 [ # # ]: 0 : if (!created_result_set) {
244 [ # # ][ # # ]: 0 : err = imesh->unite( result, (iBase_EntitySetHandle)ent->mesh_handle(), result );
245 [ # # ]: 0 : IBERRCHK(err,"WTF?");
246 : 0 : created_result_set = true;
247 : : }
248 : : else {
249 : : iBase_EntitySetHandle tmp;
250 [ # # ][ # # ]: 0 : err = imesh->unite( result, (iBase_EntitySetHandle)ent->mesh_handle(), tmp );
251 [ # # ]: 0 : IBERRCHK(err,"WTF?");
252 [ # # ]: 0 : imesh->destroyEntSet( result );
253 : 0 : result = tmp;
254 : : }
255 : : }
256 : : }
257 : 0 : catch (...) {
258 [ # # ]: 0 : if (created_result_set)
259 [ # # ]: 0 : imesh->destroyEntSet( result );
260 : 0 : throw;
261 : : }
262 : :
263 [ + - ][ - + ]: 2 : if (ent->dimension() == 3) {
264 : 0 : adj.clear();
265 [ # # ]: 0 : ent->get_adjacencies( 2, adj );
266 [ # # ][ # # ]: 0 : for (MEntVector::iterator i = adj.begin(); i != adj.end(); ++i) {
[ # # ]
267 [ # # ][ # # ]: 0 : MEntSet::iterator j = from_this.find(*i);
268 [ # # ][ # # ]: 0 : if (j != from_this.end()) {
269 [ # # ][ # # ]: 0 : front.push_back( *j );
270 [ # # ]: 0 : from_this.erase( j );
271 : : }
272 : 0 : adj2.clear();
273 [ # # ][ # # ]: 0 : (*i)->get_adjacencies( 3, adj2 );
274 [ # # ][ # # ]: 0 : for (MEntVector::iterator k = adj2.begin(); k != adj2.end(); ++k) {
[ # # ]
275 [ # # ][ # # ]: 0 : j = from_this.find(*k);
276 [ # # ][ # # ]: 0 : if (j != from_this.end()) {
277 [ # # ][ # # ]: 0 : front.push_back( *j );
278 [ # # ]: 0 : from_this.erase( j );
279 : : }
280 : : }
281 : : }
282 : : }
283 : :
284 : 2 : adj.clear();
285 [ + - ]: 2 : ent->get_adjacencies( 1, adj );
286 [ + - ][ + - ]: 10 : for (MEntVector::iterator i = adj.begin(); i != adj.end(); ++i) {
[ + + ]
287 [ + + ]: 24 : for (int dim = 2; dim <= 3; ++dim) {
288 : 16 : adj2.clear();
289 [ + - ][ + - ]: 16 : (*i)->get_adjacencies( dim, adj2 );
290 [ + - ][ + - ]: 40 : for (MEntVector::iterator k = adj2.begin(); k != adj2.end(); ++k) {
[ + + ]
291 [ + - ][ + - ]: 24 : MEntSet::iterator j = from_this.find(*k);
292 [ + - ][ - + ]: 24 : if (j != from_this.end()) {
293 [ # # ][ # # ]: 0 : front.push_back( *j );
294 [ # # ]: 0 : from_this.erase( j );
295 : : }
296 : : }
297 : : }
298 : : }
299 : 2 : }
300 : 2 : }
301 : :
302 : :
303 : 5 : void MesquiteOpt::execute_this()
304 : : {
305 [ + - ]: 5 : MEntSelection::iterator i;
306 [ + - ]: 5 : MsqError err;
307 [ + - ][ + - ]: 5 : iMesh* imesh = mk_core()->imesh_instance();
308 [ + - ][ + - ]: 5 : iGeom* igeom = mk_core()->igeom_instance();
309 : :
310 : : IQInterface* smoother;
311 [ + - ]: 10 : DefaultAlgorithm defaultAlgo;
312 [ + - ]: 5 : if (msqAlgo == 0) {
313 : 5 : smoother = &defaultAlgo;
314 [ + - ]: 5 : if (!verboseOutput)
315 [ + - ][ + - ]: 5 : defaultAlgo.quality_assessor().disable_printing_results();
316 : : }
317 : : else
318 : 0 : smoother = msqAlgo;
319 : :
320 [ + - ]: 5 : create_byte_tag();
321 : :
322 [ + - ][ + - ]: 10 : MsqIMesh msqmesh( imesh->instance(), iBase_ALL_TYPES, err, &fixedTag );
323 [ + - ][ - + ]: 5 : MSQERRCHK(err);
[ # # ][ # # ]
324 : :
325 [ + + ]: 5 : if (fixedBoundary) {
326 [ + + ]: 9 : for (int dim = 2; dim <= 3; ++dim) {
327 [ + - ][ + - ]: 12 : for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
[ + + ]
328 [ + - ]: 6 : ModelEnt* ent = i->first;
329 [ + - ][ + + ]: 6 : if (ent->dimension() != dim)
330 : 3 : continue;
331 : :
332 [ + - ]: 3 : set_fixed_tag( ent, 0 );
333 [ + - ]: 3 : set_fixed_tag_on_skin( ent, 1 );
334 : : MsqIMesh msqmesh( imesh->instance(),
335 [ + - ]: 3 : (iBase_EntitySetHandle)ent->mesh_handle(),
336 : : (iBase_EntityType)dim,
337 [ + - ][ + - ]: 3 : err, &fixedTag );
338 [ + - ][ - + ]: 3 : MSQERRCHK(err);
[ # # ][ # # ]
339 : :
340 [ + - ][ + - ]: 3 : if (ent->dimension() == 2 && ent->geom_handle()) {
[ + - ][ + - ]
[ + - ]
341 : : #ifndef HAVE_CGM
342 : : throw Error(MK_BAD_GEOMETRIC_EVALUATION,
343 : : "Mesquite not configured with iGeom support. "
344 : : "Cannot optimize surface meshes.");
345 : : #else
346 [ + - ][ + - ]: 3 : MsqIGeom msqgeom( igeom->instance(), ent->geom_handle() );
[ + - ]
347 [ + - ]: 6 : MeshDomainAssoc mesh_and_domain(&msqmesh, &msqgeom);
348 [ + - ]: 6 : smoother->run_instructions( &mesh_and_domain, err );
349 : : #endif
350 : : }
351 : : else {
352 [ # # ]: 0 : MeshDomainAssoc mesh_and_domain(&msqmesh,0);
353 [ # # ]: 0 : smoother->run_instructions( &msqmesh, err );
354 : : }
355 [ + - ][ - + ]: 3 : MSQERRCHK(err);
[ # # ][ # # ]
356 : 3 : }
357 : : }
358 : : }
359 : : else {
360 : : // shouuld be checked by FreeSmoothDomain
361 : : //if (!all_model_ents_have_geom())
362 : : // throw Error(MK_BAD_GEOMETRIC_EVALUATION,
363 : : // "Cannot do free smooth of entity that doesn't have bounding geometry.");
364 : :
365 [ + - ]: 2 : MEntSet remaining;
366 [ + - ][ + - ]: 4 : for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
[ + + ]
367 [ + - ]: 2 : ModelEnt* ent = i->first;
368 : 2 : MEntSet::iterator hint = remaining.begin();
369 [ + - ][ - + ]: 2 : if (ent->dimension() == 2 || ent->dimension() == 3)
[ # # ][ # # ]
[ + - ]
370 [ + - ]: 2 : hint = remaining.insert( hint, ent );
371 : : }
372 : :
373 [ + - ]: 4 : MEntVector ents;
374 [ + + ]: 4 : while (!remaining.empty()) {
375 : : iBase_EntitySetHandle set;
376 : 2 : bool free_set = false;
377 : : iBase_EntityType dim;
378 : 2 : ents.clear();
379 [ + - ]: 2 : get_adjacent_entity_set( remaining, ents, set, dim, free_set );
380 : :
381 : : try {
382 [ + - ][ + - ]: 2 : FreeSmoothDomain msqgeom( mk_core(), ents );
383 [ + - ][ + - ]: 4 : MsqIMesh msqmesh( imesh->instance(), set, dim, err, &fixedTag );
384 [ + - ][ - + ]: 2 : MSQERRCHK(err);
[ # # ][ # # ]
385 [ + - ]: 4 : MeshDomainAssoc mesh_and_domain(&msqmesh, &msqgeom);
386 [ + - ]: 2 : smoother->run_instructions( &mesh_and_domain, err );
387 [ + - ][ - + ]: 4 : MSQERRCHK(err);
[ # # ][ # # ]
388 : : }
389 : 0 : catch (...) {
390 [ # # ]: 0 : if (free_set)
391 [ # # ]: 0 : imesh->destroyEntSet( set );
392 : 0 : throw;
393 : : }
394 : 2 : }
395 : 5 : }
396 : 5 : }
397 : :
398 [ + - ][ + - ]: 156 : } // namespace MeshKit
399 : :
|