Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #ifdef WIN32
17 : : #ifdef _DEBUG
18 : : // turn off warnings that say they debugging identifier has been truncated
19 : : // this warning comes up when using some STL containers
20 : : #pragma warning( disable : 4786 )
21 : : #endif
22 : : #endif
23 : :
24 : : #include "moab/HigherOrderFactory.hpp"
25 : : #include "SequenceManager.hpp"
26 : : #include "UnstructuredElemSeq.hpp"
27 : : #include "VertexSequence.hpp"
28 : : #include "AEntityFactory.hpp"
29 : : #include "moab/Core.hpp"
30 : : #include "moab/CN.hpp"
31 : : #include <assert.h>
32 : : #include <algorithm>
33 : :
34 : : namespace moab
35 : : {
36 : :
37 : : using namespace std;
38 : :
39 : 8 : HigherOrderFactory::HigherOrderFactory( Core* MB, Interface::HONodeAddedRemoved* function_object )
40 : 8 : : mMB( MB ), mHONodeAddedRemoved( function_object )
41 : : {
42 : 8 : initialize_map();
43 : 8 : }
44 : 8 : HigherOrderFactory::~HigherOrderFactory() {}
45 : :
46 : : // bool HigherOrderFactory::mMapInitialized = false;
47 : :
48 : 8 : void HigherOrderFactory::initialize_map()
49 : : {
50 : : // if(mMapInitialized)
51 : : // return;
52 : :
53 [ + - ][ + + ]: 104 : for( EntityType i = MBVERTEX; i < MBMAXTYPE; i++ )
54 : : {
55 : 96 : const CN::ConnMap& canon_map = CN::mConnectivityMap[i][0];
56 : 96 : unsigned char( &this_map )[8][8] = mNodeMap[i];
57 [ + - ]: 96 : int num_node = CN::VerticesPerEntity( i );
58 [ + + ]: 520 : for( int j = 0; j < canon_map.num_sub_elements; j++ )
59 : : {
60 : 424 : unsigned char x = canon_map.conn[j][0];
61 : 424 : unsigned char y = canon_map.conn[j][1];
62 : 424 : this_map[x][y] = num_node;
63 : 424 : this_map[y][x] = num_node;
64 : 424 : num_node++;
65 : : }
66 : : }
67 : :
68 : : // mMapInitialized = true;
69 : 8 : }
70 : :
71 : 8 : ErrorCode HigherOrderFactory::convert( const EntityHandle meshset, const bool mid_edge_nodes, const bool mid_face_nodes,
72 : : const bool mid_volume_nodes )
73 : : {
74 [ + - ]: 8 : Range entities;
75 [ + - ]: 8 : mMB->get_entities_by_handle( meshset, entities, true );
76 [ + - ]: 8 : return convert( entities, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
77 : : }
78 : :
79 : 8 : ErrorCode HigherOrderFactory::convert( const Range& entities, const bool mid_edge_nodes, const bool mid_face_nodes,
80 : : const bool mid_volume_nodes )
81 : :
82 : : {
83 : :
84 : : // TODO -- add some more code to prevent from splitting of entity sequences when we don't need
85 : : // to. Say we have all hex8's in our mesh and 3 falses are passed in. In the end, no conversion
86 : : // will happen, but the sequences could still be split up.
87 : :
88 : : // find out what entity sequences we need to convert
89 : : // and where, if necessary, to split them
90 : :
91 [ + - ]: 8 : SequenceManager* seq_manager = mMB->sequence_manager();
92 [ + - ]: 8 : Range::const_pair_iterator p_iter;
93 [ + - ][ + - ]: 17 : for( p_iter = entities.const_pair_begin(); p_iter != entities.const_pair_end(); ++p_iter )
[ + - ][ + - ]
[ + + ]
94 : : {
95 : :
96 [ + - ]: 9 : EntityHandle h = p_iter->first;
97 [ + - ][ + + ]: 22 : while( h <= p_iter->second )
98 : : {
99 : :
100 : : EntitySequence* seq;
101 [ + - ]: 13 : ErrorCode rval = seq_manager->find( h, seq );
102 [ - + ]: 13 : if( MB_SUCCESS != rval ) return rval;
103 : :
104 [ + - ][ + - ]: 13 : if( seq->type() == MBVERTEX || seq->type() >= MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
[ + - ][ - + ]
[ - + ]
105 : :
106 : : // make sequence is not structured mesh
107 : 13 : ElementSequence* elemseq = static_cast< ElementSequence* >( seq );
108 [ + - ][ - + ]: 13 : if( NULL == elemseq->get_connectivity_array() ) return MB_NOT_IMPLEMENTED;
109 : :
110 [ + - ]: 13 : EntityHandle last = p_iter->second;
111 [ + - ][ + + ]: 13 : if( last > seq->end_handle() ) last = seq->end_handle();
[ + - ]
112 : :
113 [ + - ]: 13 : rval = convert_sequence( elemseq, h, last, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
114 [ - + ]: 13 : if( MB_SUCCESS != rval ) return rval;
115 : :
116 : 13 : h = last + 1;
117 : : }
118 : : }
119 : :
120 : 8 : return MB_SUCCESS;
121 : : }
122 : :
123 : 13 : ErrorCode HigherOrderFactory::convert_sequence( ElementSequence* seq, EntityHandle start, EntityHandle end,
124 : : bool mid_edge_nodes, bool mid_face_nodes, bool mid_volume_nodes )
125 : : {
126 : :
127 : 13 : ErrorCode status = MB_SUCCESS;
128 : :
129 : : // lets make sure parameters are ok before we continue
130 [ + - ]: 13 : switch( seq->type() )
[ - - + + ]
131 : : {
132 : : default:
133 : 0 : return MB_TYPE_OUT_OF_RANGE;
134 : : case MBEDGE:
135 : 0 : mid_face_nodes = false;
136 : : case MBTRI:
137 : : case MBQUAD:
138 : 2 : mid_volume_nodes = false;
139 : : case MBTET:
140 : : case MBHEX:
141 : : case MBPRISM:
142 : : case MBPYRAMID:
143 : : case MBKNIFE:
144 : 13 : break;
145 : : }
146 : :
147 : : // calculate number of nodes in target configuration
148 [ + - ][ + - ]: 13 : unsigned nodes_per_elem = CN::VerticesPerEntity( seq->type() );
149 [ + + ][ + - ]: 13 : if( mid_edge_nodes ) nodes_per_elem += ( seq->type() == MBEDGE ) ? 1 : CN::NumSubEntities( seq->type(), 1 );
[ + - ][ + - ]
[ + - ]
150 [ + + ]: 13 : if( mid_face_nodes )
151 [ + - ][ + - ]: 6 : nodes_per_elem += ( CN::Dimension( seq->type() ) == 2 ) ? 1 : CN::NumSubEntities( seq->type(), 2 );
[ + + ][ + - ]
[ + - ]
152 [ + + ]: 13 : if( mid_volume_nodes ) nodes_per_elem += 1;
153 : :
154 [ + - ][ - + ]: 13 : if( nodes_per_elem == seq->nodes_per_element() ) return MB_SUCCESS;
155 : :
156 : : Tag deletable_nodes;
157 [ + - ]: 13 : status = mMB->tag_get_handle( 0, 1, MB_TYPE_BIT, deletable_nodes, MB_TAG_CREAT | MB_TAG_BIT );
158 [ - + ]: 13 : if( MB_SUCCESS != status ) return status;
159 : :
160 [ + - ][ + - ]: 13 : UnstructuredElemSeq* new_seq = new UnstructuredElemSeq( start, end - start + 1, nodes_per_elem, end - start + 1 );
161 : :
162 [ + - ]: 13 : copy_corner_nodes( seq, new_seq );
163 : :
164 [ + - ][ + + ]: 13 : if( seq->has_mid_edge_nodes() && mid_edge_nodes )
[ - + ][ - + ]
165 [ # # ]: 0 : status = copy_mid_edge_nodes( seq, new_seq );
166 [ + - ][ + + ]: 13 : else if( seq->has_mid_edge_nodes() && !mid_edge_nodes )
[ + - ][ + + ]
167 [ + - ]: 2 : status = remove_mid_edge_nodes( seq, start, end, deletable_nodes );
168 [ + - ][ + - ]: 11 : else if( !seq->has_mid_edge_nodes() && mid_edge_nodes )
[ + + ][ + + ]
169 [ + - ]: 8 : status = zero_mid_edge_nodes( new_seq );
170 [ - + ]: 13 : if( MB_SUCCESS != status ) return status;
171 : :
172 [ + - ][ - + ]: 13 : if( seq->has_mid_face_nodes() && mid_face_nodes )
[ # # ][ - + ]
173 [ # # ]: 0 : status = copy_mid_face_nodes( seq, new_seq );
174 [ + - ][ - + ]: 13 : else if( seq->has_mid_face_nodes() && !mid_face_nodes )
[ # # ][ - + ]
175 [ # # ]: 0 : status = remove_mid_face_nodes( seq, start, end, deletable_nodes );
176 [ + - ][ + - ]: 13 : else if( !seq->has_mid_face_nodes() && mid_face_nodes )
[ + + ][ + + ]
177 [ + - ]: 6 : status = zero_mid_face_nodes( new_seq );
178 [ - + ]: 13 : if( MB_SUCCESS != status )
179 : : {
180 [ # # ]: 0 : mMB->tag_delete( deletable_nodes );
181 : 0 : return status;
182 : : }
183 : :
184 [ + - ][ - + ]: 13 : if( seq->has_mid_volume_nodes() && mid_volume_nodes )
[ # # ][ - + ]
185 [ # # ]: 0 : status = copy_mid_volume_nodes( seq, new_seq );
186 [ + - ][ - + ]: 13 : else if( seq->has_mid_volume_nodes() && !mid_volume_nodes )
[ # # ][ - + ]
187 [ # # ]: 0 : status = remove_mid_volume_nodes( seq, start, end, deletable_nodes );
188 [ + - ][ + - ]: 13 : else if( !seq->has_mid_volume_nodes() && mid_volume_nodes )
[ + + ][ + + ]
189 [ + - ]: 4 : status = zero_mid_volume_nodes( new_seq );
190 [ - + ]: 13 : if( MB_SUCCESS != status )
191 : : {
192 [ # # ]: 0 : mMB->tag_delete( deletable_nodes );
193 : 0 : return status;
194 : : }
195 : :
196 : : // gather nodes that were marked
197 [ + - ]: 13 : Range nodes;
198 [ + - ]: 13 : mMB->get_entities_by_type_and_tag( 0, MBVERTEX, &deletable_nodes, NULL, 1, nodes );
199 : :
200 : : // EntityHandle low_meshset;
201 : : // int dum;
202 : : // low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);
203 : :
204 [ + - ][ + - ]: 394 : for( Range::iterator iter = nodes.begin(); iter != nodes.end(); ++iter )
[ + - ][ + - ]
[ + + ]
205 : : {
206 : 381 : unsigned char marked = 0;
207 [ + - ][ + - ]: 381 : mMB->tag_get_data( deletable_nodes, &( *iter ), 1, &marked );
208 [ + + ]: 381 : if( marked )
209 : : {
210 : : // we can delete it
211 [ - + ][ # # ]: 177 : if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_removed( *iter );
[ # # ]
212 [ + - ][ + - ]: 177 : mMB->delete_entities( &( *iter ), 1 );
213 : : }
214 : : }
215 : :
216 [ + - ][ + + ]: 13 : const bool create_midedge = !seq->has_mid_edge_nodes() && mid_edge_nodes;
[ + + ]
217 [ + - ][ + - ]: 13 : const bool create_midface = !seq->has_mid_face_nodes() && mid_face_nodes;
[ + + ]
218 [ + - ][ + - ]: 13 : const bool create_midvolm = !seq->has_mid_volume_nodes() && mid_volume_nodes;
[ + + ]
219 : :
220 [ + - ]: 13 : mMB->tag_delete( deletable_nodes );
221 : :
222 [ + - ][ + - ]: 13 : status = mMB->sequence_manager()->replace_subsequence( new_seq );
223 [ - + ]: 13 : if( MB_SUCCESS != status )
224 : : {
225 [ # # ]: 0 : SequenceData* data = new_seq->data();
226 [ # # ]: 0 : delete new_seq;
227 [ # # ]: 0 : delete data;
228 : 0 : return status;
229 : : }
230 : :
231 [ + + ]: 13 : if( create_midedge )
232 : : {
233 [ + - ]: 8 : status = add_mid_edge_nodes( new_seq );
234 [ - + ]: 8 : if( MB_SUCCESS != status ) return status;
235 : : }
236 [ + + ]: 13 : if( create_midface )
237 : : {
238 [ + - ]: 6 : status = add_mid_face_nodes( new_seq );
239 [ - + ]: 6 : if( MB_SUCCESS != status ) return status;
240 : : }
241 [ + + ]: 13 : if( create_midvolm )
242 : : {
243 [ + - ]: 4 : status = add_mid_volume_nodes( new_seq );
244 [ - + ]: 4 : if( MB_SUCCESS != status ) return status;
245 : : }
246 : :
247 : 13 : return status;
248 : : }
249 : :
250 : 4 : ErrorCode HigherOrderFactory::add_mid_volume_nodes( ElementSequence* seq )
251 : : {
252 : 4 : EntityType this_type = seq->type();
253 : 4 : SequenceManager* seq_manager = mMB->sequence_manager();
254 : :
255 : : // find out where in the connectivity list to add these new mid volume nodes
256 [ + + ]: 4 : int edge_factor = seq->has_mid_edge_nodes() ? 1 : 0;
257 [ + + ]: 4 : int face_factor = seq->has_mid_face_nodes() ? 1 : 0;
258 : : // offset by number of higher order nodes on edges if they exist
259 : 4 : int num_corner_nodes = CN::VerticesPerEntity( this_type );
260 : 4 : int new_node_index = num_corner_nodes;
261 : 4 : new_node_index += edge_factor * CN::mConnectivityMap[this_type][0].num_sub_elements;
262 : 4 : new_node_index += face_factor * CN::mConnectivityMap[this_type][1].num_sub_elements;
263 : :
264 : 4 : EntityHandle* element = seq->get_connectivity_array();
265 : 4 : EntityHandle curr_handle = seq->start_handle();
266 : 4 : int nodes_per_element = seq->nodes_per_element();
267 : 4 : EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
268 : :
269 : : // iterate over the elements
270 [ + + ]: 36 : for( ; element < end_element; element += nodes_per_element )
271 : : {
272 : : // find the centroid of this element
273 : 32 : double tmp_coords[3], sum_coords[3] = { 0, 0, 0 };
274 : 32 : EntitySequence* eseq = NULL;
275 [ + + ]: 288 : for( int i = 0; i < num_corner_nodes; i++ )
276 : : {
277 [ + - ]: 256 : seq_manager->find( element[i], eseq );
278 : 256 : static_cast< VertexSequence* >( eseq )->get_coordinates( element[i], tmp_coords[0], tmp_coords[1],
279 [ + - ]: 256 : tmp_coords[2] );
280 : 256 : sum_coords[0] += tmp_coords[0];
281 : 256 : sum_coords[1] += tmp_coords[1];
282 : 256 : sum_coords[2] += tmp_coords[2];
283 : : }
284 : 32 : sum_coords[0] /= num_corner_nodes;
285 : 32 : sum_coords[1] /= num_corner_nodes;
286 : 32 : sum_coords[2] /= num_corner_nodes;
287 : :
288 : : // create a new vertex at the centroid
289 [ + - ]: 32 : mMB->create_vertex( sum_coords, element[new_node_index] );
290 : :
291 [ + + ][ + - ]: 32 : if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_added( element[new_node_index], curr_handle );
292 : :
293 : 32 : curr_handle++;
294 : : }
295 : :
296 : 4 : return MB_SUCCESS;
297 : : }
298 : :
299 : 6 : ErrorCode HigherOrderFactory::add_mid_face_nodes( ElementSequence* seq )
300 : : {
301 [ + - ]: 6 : EntityType this_type = seq->type();
302 [ + - ]: 6 : SequenceManager* seq_manager = mMB->sequence_manager();
303 [ + - ]: 6 : int num_vertices = CN::VerticesPerEntity( this_type );
304 : 6 : int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;
305 [ + - ][ + + ]: 6 : num_edges = seq->has_mid_edge_nodes() ? num_edges : 0;
306 : 6 : int num_faces = CN::mConnectivityMap[this_type][1].num_sub_elements;
307 : :
308 : 6 : const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
309 : :
310 [ + - ]: 6 : EntityHandle* element = seq->get_connectivity_array();
311 [ + - ]: 6 : EntityHandle curr_handle = seq->start_handle();
312 [ + - ]: 6 : int nodes_per_element = seq->nodes_per_element();
313 [ + - ]: 6 : EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
314 : :
315 : : EntityHandle tmp_face_conn[4]; // max face nodes = 4
316 [ + - ]: 6 : std::vector< EntityHandle > adjacent_entities( 4 );
317 : :
318 : : double tmp_coords[3];
319 : :
320 : : // iterate over the elements
321 [ + + ]: 98 : for( ; element < end_element; element += nodes_per_element )
322 : : {
323 : : // for each edge in this entity
324 [ + + ]: 396 : for( int i = 0; i < num_faces; i++ )
325 : : {
326 : : // a node was already assigned
327 [ - + ]: 304 : if( element[i + num_edges + num_vertices] != 0 ) continue;
328 : :
329 : 304 : tmp_face_conn[0] = element[entity_faces.conn[i][0]];
330 : 304 : tmp_face_conn[1] = element[entity_faces.conn[i][1]];
331 : 304 : tmp_face_conn[2] = element[entity_faces.conn[i][2]];
332 [ + + ]: 304 : if( entity_faces.num_corners_per_sub_element[i] == 4 )
333 : 96 : tmp_face_conn[3] = element[entity_faces.conn[i][3]];
334 : : else
335 : 208 : tmp_face_conn[3] = 0;
336 : :
337 [ + - ]: 304 : EntityHandle already_made_node = center_node_exist( tmp_face_conn, adjacent_entities );
338 : :
339 [ + + ]: 304 : if( already_made_node ) { element[i + num_edges + num_vertices] = already_made_node; }
340 : : // create a node
341 : : else
342 : : {
343 : 249 : EntitySequence* tmp_sequence = NULL;
344 : 249 : double sum_coords[3] = { 0, 0, 0 };
345 : 249 : int max_nodes = entity_faces.num_corners_per_sub_element[i];
346 [ + + ]: 1089 : for( int k = 0; k < max_nodes; k++ )
347 : : {
348 [ + - ]: 840 : seq_manager->find( tmp_face_conn[k], tmp_sequence );
349 : : static_cast< VertexSequence* >( tmp_sequence )
350 [ + - ]: 840 : ->get_coordinates( tmp_face_conn[k], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
351 : 840 : sum_coords[0] += tmp_coords[0];
352 : 840 : sum_coords[1] += tmp_coords[1];
353 : 840 : sum_coords[2] += tmp_coords[2];
354 : : }
355 : :
356 : 249 : sum_coords[0] /= max_nodes;
357 : 249 : sum_coords[1] /= max_nodes;
358 : 249 : sum_coords[2] /= max_nodes;
359 : :
360 [ + - ]: 249 : mMB->create_vertex( sum_coords, element[i + num_edges + num_vertices] );
361 : : }
362 : :
363 [ - + ]: 304 : if( mHONodeAddedRemoved )
364 [ # # ]: 0 : mHONodeAddedRemoved->node_added( element[i + num_edges + num_vertices], curr_handle );
365 : : }
366 : :
367 : 92 : curr_handle++;
368 : : }
369 : :
370 : 6 : return MB_SUCCESS;
371 : : }
372 : :
373 : 8 : ErrorCode HigherOrderFactory::add_mid_edge_nodes( ElementSequence* seq )
374 : : {
375 : : // for each node, need to see if it was already created.
376 [ + - ]: 8 : EntityType this_type = seq->type();
377 [ + - ]: 8 : SequenceManager* seq_manager = mMB->sequence_manager();
378 : :
379 : : // offset by number of corner nodes
380 [ + - ]: 8 : int num_vertices = CN::VerticesPerEntity( this_type );
381 : 8 : int num_edges = CN::mConnectivityMap[this_type][0].num_sub_elements;
382 : :
383 : 8 : const CN::ConnMap& entity_edges = CN::mConnectivityMap[this_type][0];
384 : :
385 [ + - ]: 8 : EntityHandle* element = seq->get_connectivity_array();
386 [ + - ]: 8 : EntityHandle curr_handle = seq->start_handle();
387 [ + - ]: 8 : int nodes_per_element = seq->nodes_per_element();
388 [ + - ]: 8 : EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
389 : :
390 : : EntityHandle tmp_edge_conn[2];
391 [ + - ]: 8 : std::vector< EntityHandle > adjacent_entities( 32 );
392 : :
393 : : double tmp_coords[3];
394 : :
395 : : // iterate over the elements
396 [ + + ]: 116 : for( ; element < end_element; element += nodes_per_element )
397 : : {
398 : : // for each edge in this entity
399 [ + + ]: 852 : for( int i = 0; i < num_edges; i++ )
400 : : {
401 : : // a node was already assigned
402 [ - + ]: 744 : if( element[i + num_vertices] != 0 ) continue;
403 : :
404 : 744 : tmp_edge_conn[0] = element[entity_edges.conn[i][0]];
405 : 744 : tmp_edge_conn[1] = element[entity_edges.conn[i][1]];
406 : :
407 [ + - ]: 744 : EntityHandle already_made_node = center_node_exist( tmp_edge_conn[0], tmp_edge_conn[1], adjacent_entities );
408 : :
409 [ + + ]: 744 : if( already_made_node ) { element[i + num_vertices] = already_made_node; }
410 : : // create a node
411 : : else
412 : : {
413 : 522 : EntitySequence* tmp_sequence = NULL;
414 : 522 : double sum_coords[3] = { 0, 0, 0 };
415 [ + - ]: 522 : seq_manager->find( tmp_edge_conn[0], tmp_sequence );
416 : : static_cast< VertexSequence* >( tmp_sequence )
417 [ + - ]: 522 : ->get_coordinates( tmp_edge_conn[0], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
418 : 522 : sum_coords[0] += tmp_coords[0];
419 : 522 : sum_coords[1] += tmp_coords[1];
420 : 522 : sum_coords[2] += tmp_coords[2];
421 [ + - ]: 522 : seq_manager->find( tmp_edge_conn[1], tmp_sequence );
422 : : static_cast< VertexSequence* >( tmp_sequence )
423 [ + - ]: 522 : ->get_coordinates( tmp_edge_conn[1], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
424 : 522 : sum_coords[0] = ( sum_coords[0] + tmp_coords[0] ) / 2;
425 : 522 : sum_coords[1] = ( sum_coords[1] + tmp_coords[1] ) / 2;
426 : 522 : sum_coords[2] = ( sum_coords[2] + tmp_coords[2] ) / 2;
427 : :
428 [ + - ]: 522 : mMB->create_vertex( sum_coords, element[i + num_vertices] );
429 : : }
430 : :
431 [ - + ][ # # ]: 744 : if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_added( element[i + num_vertices], curr_handle );
432 : : }
433 : :
434 : 108 : curr_handle++;
435 : : }
436 : :
437 : 8 : return MB_SUCCESS;
438 : : }
439 : :
440 : 744 : EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corner1, EntityHandle corner2,
441 : : std::vector< EntityHandle >& adj_entities )
442 : : {
443 [ + - ]: 744 : AEntityFactory* a_fact = mMB->a_entity_factory();
444 [ + - ]: 744 : std::vector< EntityHandle > adj_corner1( 32 );
445 [ + - ]: 1488 : std::vector< EntityHandle > adj_corner2( 32 );
446 : :
447 : : // create needed vertex adjacencies
448 [ + - ][ + + ]: 744 : if( !a_fact->vert_elem_adjacencies() ) a_fact->create_vert_elem_adjacencies();
[ + - ]
449 : :
450 : : // vectors are returned sorted
451 : :
452 [ + - ]: 744 : a_fact->get_adjacencies( corner1, adj_corner1 );
453 [ + - ]: 744 : a_fact->get_adjacencies( corner2, adj_corner2 );
454 : :
455 : : // these are the entities adjacent to both nodes
456 : 744 : adj_entities.clear();
457 : : std::set_intersection( adj_corner1.begin(), adj_corner1.end(), adj_corner2.begin(), adj_corner2.end(),
458 [ + - ][ + - ]: 744 : std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
459 : :
460 : : // iterate of the entities to find a mid node
461 : : const EntityHandle* conn;
462 : 744 : int conn_size = 0;
463 [ + - ][ + + ]: 1534 : for( std::vector< EntityHandle >::iterator iter = adj_entities.begin(); iter != adj_entities.end(); )
464 : : {
465 [ + - ][ + - ]: 1012 : EntityType this_type = TYPE_FROM_HANDLE( *iter );
466 [ + + ]: 1012 : if( this_type == MBENTITYSET )
467 : : {
468 [ + - ]: 78 : ++iter;
469 : 78 : continue;
470 : : }
471 [ + - ][ + - ]: 934 : mMB->get_connectivity( *iter, conn, conn_size );
472 : : // if this entity has mid edge nodes
473 [ + - ][ + + ]: 934 : if( CN::HasMidEdgeNodes( this_type, conn_size ) )
474 : : {
475 : : // find out at which index the mid node should be at
476 [ + - ]: 602 : int first_node = std::find( conn, conn + conn_size, corner1 ) - conn;
477 [ + - ]: 602 : int second_node = std::find( conn, conn + conn_size, corner2 ) - conn;
478 [ + - ][ - + ]: 602 : if( first_node == conn_size || second_node == conn_size )
479 : 0 : assert( "We should always find our nodes no matter what" == NULL );
480 : 602 : int high_node_index = mNodeMap[this_type][first_node][second_node];
481 [ + + ]: 602 : if( conn[high_node_index] != 0 ) return conn[high_node_index];
482 [ + - ]: 380 : ++iter;
483 : : }
484 : : else
485 : : {
486 [ + - ]: 332 : iter = adj_entities.erase( iter );
487 : : }
488 : : }
489 : :
490 : 1266 : return 0;
491 : : }
492 : :
493 : 304 : EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corners[4], std::vector< EntityHandle >& adj_entities )
494 : : {
495 [ + - ]: 304 : AEntityFactory* a_fact = mMB->a_entity_factory();
496 [ + - ][ + + ]: 2736 : std::vector< EntityHandle > adj_corner[4];
[ # # ]
497 [ + + ]: 304 : int num_nodes = corners[3] == 0 ? 3 : 4;
498 : 304 : int i = 0;
499 : :
500 : : // create needed vertex adjacencies
501 [ + - ][ - + ]: 304 : if( !a_fact->vert_elem_adjacencies() ) a_fact->create_vert_elem_adjacencies();
[ # # ]
502 : :
503 : : // vectors are returned sorted
504 [ + + ]: 1312 : for( i = 0; i < num_nodes; i++ )
505 [ + - ]: 1008 : a_fact->get_adjacencies( corners[i], adj_corner[i] );
506 : :
507 : : // these are the entities adjacent to both nodes
508 [ + + ]: 1008 : for( i = 1; i < num_nodes; i++ )
509 : : {
510 : 704 : adj_entities.clear();
511 : 1408 : std::set_intersection( adj_corner[i - 1].begin(), adj_corner[i - 1].end(), adj_corner[i].begin(),
512 [ + - ][ + - ]: 704 : adj_corner[i].end(), std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
513 : 704 : adj_corner[i].swap( adj_entities );
514 : : }
515 : 304 : adj_entities.swap( adj_corner[i - 1] );
516 : :
517 : : // iterate of the entities to find a mid node
518 : : const EntityHandle* conn;
519 : 304 : int conn_size = 0;
520 [ + - ][ + + ]: 622 : for( std::vector< EntityHandle >::iterator iter = adj_entities.begin(); iter != adj_entities.end(); )
521 : : {
522 [ + - ][ + - ]: 373 : EntityType this_type = TYPE_FROM_HANDLE( *iter );
523 [ + + ]: 373 : if( this_type == MBENTITYSET )
524 : : {
525 [ + - ]: 36 : ++iter;
526 : 36 : continue;
527 : : }
528 : 337 : const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
529 [ + - ][ + - ]: 337 : mMB->get_connectivity( *iter, conn, conn_size );
530 [ + - ]: 337 : int offset = CN::VerticesPerEntity( this_type );
531 [ + - ][ + + ]: 337 : if( CN::HasMidEdgeNodes( this_type, conn_size ) ) offset += CN::mConnectivityMap[this_type][0].num_sub_elements;
532 : :
533 : : // if this entity has mid face nodes
534 [ + - ][ + + ]: 337 : if( CN::HasMidFaceNodes( this_type, conn_size ) )
535 : : {
536 : : int k;
537 : : int indexes[4];
538 [ + + ]: 1085 : for( k = 0; k < num_nodes; k++ )
539 [ + - ]: 816 : indexes[k] = std::find( conn, conn + conn_size, corners[k] ) - conn;
540 : :
541 : : // find out at which index the mid node should be at
542 [ + + ]: 854 : for( k = 0; k < entity_faces.num_sub_elements; k++ )
543 : : {
544 [ + - ][ - + ]: 640 : if( CN::VerticesPerEntity( entity_faces.target_type[k] ) != num_nodes ) continue;
545 : :
546 [ + - ]: 640 : int* pivot = std::find( indexes, indexes + num_nodes, entity_faces.conn[k][0] );
547 [ + + ]: 640 : if( pivot == indexes + num_nodes ) continue;
548 : :
549 [ + + ][ + - ]: 506 : if( pivot != indexes ) std::rotate( indexes, pivot, indexes + num_nodes );
550 : :
551 [ + - ][ + + ]: 506 : if( std::equal( indexes, indexes + num_nodes, entity_faces.conn[k] ) )
552 : : {
553 [ + + ]: 176 : if( conn[k + offset] != 0 ) return conn[k + offset];
554 : 121 : k = entity_faces.num_sub_elements;
555 : : }
556 : : else
557 : : {
558 : 357 : int temp = indexes[1];
559 : 357 : indexes[1] = indexes[num_nodes - 1];
560 : 357 : indexes[num_nodes - 1] = temp;
561 [ + - ][ + + ]: 357 : if( std::equal( indexes, indexes + num_nodes, entity_faces.conn[k] ) )
562 : : {
563 [ + + ]: 120 : if( conn[k + offset] != 0 ) return conn[k + offset];
564 : 93 : k = entity_faces.num_sub_elements;
565 : : }
566 : : }
567 : : }
568 [ + - ]: 214 : ++iter;
569 : : }
570 : : else
571 : : {
572 [ + - ]: 68 : iter = adj_entities.erase( iter );
573 : : }
574 : : }
575 : :
576 [ + + ]: 1520 : return 0;
[ # # # # ]
577 : : }
578 : :
579 : 0 : bool HigherOrderFactory::add_center_node( EntityType this_type, EntityHandle* element_conn, int conn_size,
580 : : EntityHandle corner_node1, EntityHandle corner_node2,
581 : : EntityHandle center_node )
582 : : {
583 : 0 : int first_node = std::find( element_conn, element_conn + conn_size, corner_node1 ) - element_conn;
584 : 0 : int second_node = std::find( element_conn, element_conn + conn_size, corner_node2 ) - element_conn;
585 [ # # ][ # # ]: 0 : if( first_node == conn_size || second_node == conn_size )
586 : 0 : assert( "We should always find our nodes no matter what" == NULL );
587 : 0 : int high_node_index = mNodeMap[this_type][first_node][second_node];
588 : 0 : element_conn[high_node_index] = center_node;
589 : 0 : return true;
590 : : }
591 : :
592 : 13 : ErrorCode HigherOrderFactory::copy_corner_nodes( ElementSequence* src, ElementSequence* dst )
593 : : {
594 : 13 : unsigned num_corners = CN::VerticesPerEntity( src->type() );
595 : 13 : return copy_nodes( src, dst, num_corners, 0, 0 );
596 : : }
597 : :
598 : 0 : ErrorCode HigherOrderFactory::copy_mid_edge_nodes( ElementSequence* src, ElementSequence* dst )
599 : : {
600 [ # # ][ # # ]: 0 : if( !src->has_mid_edge_nodes() || !dst->has_mid_edge_nodes() ) return MB_FAILURE;
[ # # ]
601 : :
602 : 0 : unsigned num_corners = CN::VerticesPerEntity( src->type() );
603 [ # # ]: 0 : unsigned num_edges = ( src->type() == MBEDGE ) ? 1 : CN::NumSubEntities( src->type(), 1 );
604 : 0 : return copy_nodes( src, dst, num_edges, num_corners, num_corners );
605 : : }
606 : :
607 : 8 : ErrorCode HigherOrderFactory::zero_mid_edge_nodes( ElementSequence* dst )
608 : : {
609 [ - + ]: 8 : if( !dst->has_mid_edge_nodes() ) return MB_FAILURE;
610 : :
611 : 8 : unsigned num_corners = CN::VerticesPerEntity( dst->type() );
612 [ + - ]: 8 : unsigned num_edges = ( dst->type() == MBEDGE ) ? 1 : CN::NumSubEntities( dst->type(), 1 );
613 : 8 : return zero_nodes( dst, num_edges, num_corners );
614 : : }
615 : :
616 : 0 : ErrorCode HigherOrderFactory::copy_mid_face_nodes( ElementSequence* src, ElementSequence* dst )
617 : : {
618 [ # # ][ # # ]: 0 : if( !src->has_mid_face_nodes() || !dst->has_mid_face_nodes() ) return MB_FAILURE;
[ # # ]
619 : :
620 : 0 : unsigned src_offset = CN::VerticesPerEntity( src->type() );
621 : 0 : unsigned dst_offset = src_offset;
622 [ # # ]: 0 : if( src->has_mid_edge_nodes() ) src_offset += CN::NumSubEntities( src->type(), 1 );
623 [ # # ]: 0 : if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
624 [ # # ]: 0 : unsigned num_faces = ( CN::Dimension( src->type() ) == 2 ) ? 1 : CN::NumSubEntities( src->type(), 2 );
625 : 0 : return copy_nodes( src, dst, num_faces, src_offset, dst_offset );
626 : : }
627 : :
628 : 6 : ErrorCode HigherOrderFactory::zero_mid_face_nodes( ElementSequence* dst )
629 : : {
630 [ - + ]: 6 : if( !dst->has_mid_face_nodes() ) return MB_FAILURE;
631 : :
632 : 6 : unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
633 [ + + ]: 6 : if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
634 [ + + ]: 6 : unsigned num_faces = ( CN::Dimension( dst->type() ) == 2 ) ? 1 : CN::NumSubEntities( dst->type(), 2 );
635 : 6 : return zero_nodes( dst, num_faces, dst_offset );
636 : : }
637 : :
638 : 0 : ErrorCode HigherOrderFactory::copy_mid_volume_nodes( ElementSequence* src, ElementSequence* dst )
639 : : {
640 [ # # ][ # # ]: 0 : if( !src->has_mid_volume_nodes() || !dst->has_mid_volume_nodes() ) return MB_FAILURE;
[ # # ]
641 : :
642 : 0 : unsigned src_offset = CN::VerticesPerEntity( src->type() );
643 : 0 : unsigned dst_offset = src_offset;
644 [ # # ]: 0 : if( src->has_mid_edge_nodes() ) src_offset += CN::NumSubEntities( src->type(), 1 );
645 [ # # ]: 0 : if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
646 [ # # ]: 0 : if( src->has_mid_face_nodes() ) src_offset += CN::NumSubEntities( src->type(), 2 );
647 [ # # ]: 0 : if( dst->has_mid_face_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 2 );
648 : 0 : return copy_nodes( src, dst, 1, src_offset, dst_offset );
649 : : }
650 : :
651 : 4 : ErrorCode HigherOrderFactory::zero_mid_volume_nodes( ElementSequence* dst )
652 : : {
653 [ - + ]: 4 : if( !dst->has_mid_volume_nodes() ) return MB_FAILURE;
654 : :
655 : 4 : unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
656 [ + + ]: 4 : if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
657 [ + + ]: 4 : if( dst->has_mid_face_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 2 );
658 : 4 : return zero_nodes( dst, 1, dst_offset );
659 : : }
660 : :
661 : 13 : ErrorCode HigherOrderFactory::copy_nodes( ElementSequence* src, ElementSequence* dst, unsigned nodes_per_elem,
662 : : unsigned src_offset, unsigned dst_offset )
663 : : {
664 [ - + ]: 13 : if( src->type() != dst->type() ) return MB_FAILURE;
665 : :
666 : 13 : unsigned src_stride = src->nodes_per_element();
667 : 13 : unsigned dst_stride = dst->nodes_per_element();
668 : 13 : EntityHandle* src_conn = src->get_connectivity_array();
669 : 13 : EntityHandle* dst_conn = dst->get_connectivity_array();
670 [ + - ][ - + ]: 13 : if( !src_conn || !dst_conn ) return MB_FAILURE;
671 : :
672 [ + - ][ - + ]: 13 : if( dst->start_handle() < src->start_handle() || dst->end_handle() > src->end_handle() ) return MB_FAILURE;
[ - + ]
673 : :
674 : 13 : src_conn += ( dst->start_handle() - src->start_handle() ) * src_stride;
675 : 13 : EntityID count = dst->size();
676 [ + + ]: 175 : for( EntityID i = 0; i < count; ++i )
677 : : {
678 [ + + ]: 1034 : for( unsigned j = 0; j < nodes_per_elem; ++j )
679 : 872 : dst_conn[j + dst_offset] = src_conn[j + src_offset];
680 : 162 : src_conn += src_stride;
681 : 162 : dst_conn += dst_stride;
682 : : }
683 : :
684 : 13 : return MB_SUCCESS;
685 : : }
686 : :
687 : 18 : ErrorCode HigherOrderFactory::zero_nodes( ElementSequence* dst, unsigned nodes_per_elem, unsigned offset )
688 : : {
689 : 18 : unsigned dst_stride = dst->nodes_per_element();
690 : 18 : EntityHandle* dst_conn = dst->get_connectivity_array();
691 [ - + ]: 18 : if( !dst_conn ) return MB_FAILURE;
692 : :
693 : 18 : EntityID count = dst->size();
694 [ + + ]: 250 : for( EntityID i = 0; i < count; ++i )
695 : : {
696 [ + - ]: 232 : std::fill( dst_conn + offset, dst_conn + offset + nodes_per_elem, 0 );
697 : 232 : dst_conn += dst_stride;
698 : : }
699 : :
700 : 18 : return MB_SUCCESS;
701 : : }
702 : :
703 : 2 : ErrorCode HigherOrderFactory::remove_mid_edge_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
704 : : Tag deletable_nodes )
705 : : {
706 : : int count;
707 : : int offset;
708 [ - + ]: 2 : if( seq->type() == MBEDGE )
709 : : {
710 : 0 : count = 1;
711 : 0 : offset = 2;
712 : : }
713 : : else
714 : : {
715 : 2 : count = CN::NumSubEntities( seq->type(), 1 );
716 : 2 : offset = CN::VerticesPerEntity( seq->type() );
717 : : }
718 : :
719 : 2 : return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
720 : : }
721 : :
722 : 0 : ErrorCode HigherOrderFactory::remove_mid_face_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
723 : : Tag deletable_nodes )
724 : : {
725 : : int count;
726 [ # # ]: 0 : if( CN::Dimension( seq->type() ) == 2 )
727 : 0 : count = 1;
728 : : else
729 : 0 : count = CN::NumSubEntities( seq->type(), 2 );
730 : 0 : int offset = CN::VerticesPerEntity( seq->type() );
731 [ # # ]: 0 : if( seq->has_mid_edge_nodes() ) offset += CN::NumSubEntities( seq->type(), 1 );
732 : :
733 : 0 : return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
734 : : }
735 : :
736 : 0 : ErrorCode HigherOrderFactory::remove_mid_volume_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
737 : : Tag deletable_nodes )
738 : : {
739 : 0 : int offset = CN::VerticesPerEntity( seq->type() );
740 [ # # ]: 0 : if( seq->has_mid_edge_nodes() ) offset += CN::NumSubEntities( seq->type(), 1 );
741 [ # # ]: 0 : if( seq->has_mid_face_nodes() ) offset += CN::NumSubEntities( seq->type(), 2 );
742 : :
743 : 0 : return remove_ho_nodes( seq, start, end, 1, offset, deletable_nodes );
744 : : }
745 : :
746 : : // Code mostly copied from old EntitySequence.cpp
747 : : // (ElementEntitySequence::convert_realloc &
748 : : // ElementEntitySequence::tag_for_deletion).
749 : : // Copyright from old EntitySequence.cpp:
750 : : /**
751 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
752 : : * storing and accessing finite element mesh data.
753 : : *
754 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
755 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
756 : : * retains certain rights in this software.
757 : : *
758 : : * This library is free software; you can redistribute it and/or
759 : : * modify it under the terms of the GNU Lesser General Public
760 : : * License as published by the Free Software Foundation; either
761 : : * version 2.1 of the License, or (at your option) any later version.
762 : : *
763 : : */
764 : 2 : ErrorCode HigherOrderFactory::remove_ho_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
765 : : int nodes_per_elem, int elem_conn_offset, Tag deletable_nodes )
766 : : {
767 [ + - ][ + - ]: 2 : if( start < seq->start_handle() || end > seq->end_handle() ) return MB_ENTITY_NOT_FOUND;
[ + - ][ - + ]
[ - + ]
768 [ + - ]: 2 : EntityHandle* array = seq->get_connectivity_array();
769 [ - + ]: 2 : if( !array ) return MB_NOT_IMPLEMENTED;
770 : :
771 [ + - ]: 2 : std::set< EntityHandle > nodes_processed;
772 [ + + ]: 18 : for( EntityHandle i = start; i <= end; ++i )
773 : : { // for each element
774 [ + + ]: 208 : for( int j = 0; j < nodes_per_elem; ++j )
775 : : { // for each HO node to remove
776 [ + - ]: 192 : const EntityID elem = ( i - seq->start_handle() ); // element index
777 : 192 : const int conn_idx = j + elem_conn_offset;
778 [ + - ]: 192 : const EntityID index = elem * seq->nodes_per_element() + conn_idx;
779 [ + - ][ + - ]: 192 : if( array[index] && nodes_processed.insert( array[index] ).second )
[ + + ][ + + ]
780 : : {
781 [ + - ][ + - ]: 177 : if( tag_for_deletion( i, conn_idx, seq ) )
782 : : {
783 : 177 : unsigned char bit = 0x1;
784 [ + - ]: 177 : mMB->tag_set_data( deletable_nodes, &( array[index] ), 1, &bit );
785 : : }
786 : : }
787 : : }
788 : : }
789 : :
790 : 2 : return MB_SUCCESS;
791 : : }
792 : :
793 : 177 : bool HigherOrderFactory::tag_for_deletion( EntityHandle parent_handle, int conn_index, ElementSequence* seq )
794 : : {
795 : : // get type of this sequence
796 [ + - ]: 177 : EntityType this_type = seq->type();
797 : :
798 : : // get dimension of 'parent' element
799 [ + - ]: 177 : int this_dimension = mMB->dimension_from_handle( parent_handle );
800 : :
801 : : // tells us if higher order node is on
802 : : int dimension, side_number;
803 [ + - ][ + - ]: 177 : CN::HONodeParent( this_type, seq->nodes_per_element(), conn_index, dimension, side_number );
804 : :
805 : : // it MUST be a higher-order node
806 : 177 : bool delete_node = false;
807 : :
808 [ - + ]: 177 : assert( dimension != -1 );
809 [ - + ]: 177 : assert( side_number != -1 );
810 : :
811 : : // could be a mid-volume/face/edge node on a hex/face/edge respectively
812 : : // if so...delete it bc/ no one else owns it too
813 [ + - ]: 177 : std::vector< EntityHandle > connectivity;
814 [ - + ][ # # ]: 177 : if( dimension == this_dimension && side_number == 0 )
815 : 0 : delete_node = true;
816 : : else // the node could also be on a lower order entity of 'tmp_entity'
817 : : {
818 : : // get 'side' of 'parent_handle' that node is on
819 : 177 : EntityHandle target_entity = 0;
820 [ + - ]: 177 : mMB->side_element( parent_handle, dimension, side_number, target_entity );
821 : :
822 [ - + ]: 177 : if( target_entity )
823 : : {
824 [ # # ]: 0 : AEntityFactory* a_fact = mMB->a_entity_factory();
825 : : EntityHandle low_meshset;
826 : : int dum;
827 [ # # ]: 0 : low_meshset = CREATE_HANDLE( MBENTITYSET, 0, dum );
828 : :
829 : : // just get corner nodes of target_entity
830 : 0 : connectivity.clear();
831 : : ErrorCode rval;
832 [ # # ][ # # ]: 0 : rval = mMB->get_connectivity( &( target_entity ), 1, connectivity, true );MB_CHK_ERR( rval );
[ # # ][ # # ]
833 : :
834 : : // for each node, get all common adjacencies of nodes in 'parent_handle'
835 [ # # ][ # # ]: 0 : std::vector< EntityHandle > adj_list_1, adj_list_2, adj_entities;
[ # # ]
836 [ # # ][ # # ]: 0 : a_fact->get_adjacencies( connectivity[0], adj_list_1 );
837 : :
838 : : // remove meshsets
839 : : adj_list_1.erase(
840 : : std::remove_if( adj_list_1.begin(), adj_list_1.end(),
841 : : std::bind( std::greater< EntityHandle >(), std::placeholders::_1, low_meshset ) ),
842 [ # # ][ # # ]: 0 : adj_list_1.end() );
[ # # ]
843 : : // std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_1.end());
844 : : // https://stackoverflow.com/questions/32739018/a-replacement-for-stdbind2nd
845 : :
846 : : size_t i;
847 [ # # ]: 0 : for( i = 1; i < connectivity.size(); i++ )
848 : : {
849 : 0 : adj_list_2.clear();
850 [ # # ][ # # ]: 0 : a_fact->get_adjacencies( connectivity[i], adj_list_2 );
851 : :
852 : : // remove meshsets
853 : : adj_list_2.erase(
854 : : std::remove_if( adj_list_2.begin(), adj_list_2.end(),
855 : : std::bind( std::greater< EntityHandle >(), std::placeholders::_1, low_meshset ) ),
856 [ # # ][ # # ]: 0 : adj_list_2.end() );
[ # # ]
857 : : // std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_2.end());
858 : : // https://stackoverflow.com/questions/32739018/a-replacement-for-stdbind2nd
859 : :
860 : : // intersect the 2 lists
861 : 0 : adj_entities.clear();
862 : : std::set_intersection( adj_list_1.begin(), adj_list_1.end(), adj_list_2.begin(), adj_list_2.end(),
863 [ # # ][ # # ]: 0 : std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
864 : 0 : adj_list_1.clear();
865 [ # # ]: 0 : adj_list_1 = adj_entities;
866 : : }
867 : :
868 [ # # ]: 0 : assert( adj_entities.size() ); // has to have at least one adjacency
869 : :
870 : : // see if node is in other elements, not in this sequence...if so, delete it
871 [ # # ]: 0 : for( i = 0; i < adj_entities.size(); i++ )
872 : : {
873 [ # # ][ # # ]: 0 : if( adj_entities[i] >= seq->start_handle() && adj_entities[i] <= seq->end_handle() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
874 : : {
875 : 0 : delete_node = false;
876 : 0 : break;
877 : : }
878 : : else
879 : 0 : delete_node = true;
880 : 0 : }
881 : : }
882 : : else // there is no lower order entity that also contains node
883 : 177 : delete_node = true;
884 : : }
885 : :
886 : 177 : return delete_node;
887 : : }
888 : :
889 [ + - ][ + - ]: 228 : } // namespace moab
|