Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
NestedRefine.cpp
Go to the documentation of this file.
1 #include "moab/NestedRefine.hpp"
3 #include "moab/HalfFacetRep.hpp"
4 #include "moab/CpuTimer.hpp"
5 #include "moab/ReadUtilIface.hpp"
6 #include "Internals.hpp"
7 #include "MBTagConventions.hpp"
8 
9 #ifdef MOAB_HAVE_MPI
10 #include "moab/ParallelComm.hpp"
12 #include "moab/Skinner.hpp"
13 #endif
14 
15 #include <iostream>
16 #include <cassert>
17 #include <vector>
18 #include <limits>
19 #include <cmath>
20 
21 namespace moab
22 {
23 
25  : mbImpl( impl ), pcomm( comm ), _rset( rset )
26 {
28  assert( NULL != impl );
29 
30 #ifdef MOAB_HAVE_MPI
31  // Get the Parallel Comm instance to prepare all new sets to work in parallel
32  // in case the user did not provide any arguments
33  if( !comm ) pcomm = moab::ParallelComm::get_pcomm( mbImpl, 0 );
34 #endif
35  error = initialize();
36  if( error != MB_SUCCESS )
37  {
38  std::cout << "Error initializing NestedRefine\n" << std::endl;
39  exit( 1 );
40  }
41 }
42 
44 {
45 #ifdef MOAB_HAVE_AHF
46  ahf = NULL;
47 #else
48  delete ahf;
49 #endif
50  delete tm;
51 }
52 
54 {
56 
57  tm = new CpuTimer();
58  if( !tm ) return MB_MEMORY_ALLOCATION_FAILED;
59 
60 #ifdef MOAB_HAVE_AHF
61  ahf = mbImpl->a_half_facet_rep();
62 #else
63  ahf = new HalfFacetRep( mbImpl, pcomm, _rset, true );
64  if( !ahf ) return MB_MEMORY_ALLOCATION_FAILED;
65 #endif
66 
67  // Check for mixed entity type
68  bool chk_mixed = ahf->check_mixed_entity_type();
69  if( chk_mixed ) MB_SET_ERR( MB_NOT_IMPLEMENTED, "Encountered a mesh with mixed entity types" );
70 
71  error = ahf->initialize();
72  MB_CHK_ERR( error );
74  MB_CHK_ERR( error );
75 
76  // Check for supported entity type
77  if( !_incells.empty() )
78  {
79  EntityType type = mbImpl->type_from_handle( _incells[0] );
80  if( type != MBTET && type != MBHEX )
81  MB_SET_ERR( MB_FAILURE, "Not supported 3D entity types: MBPRISM, MBPYRAMID, MBKNIFE, MBPOLYHEDRON" );
82 
83  meshdim = 3;
84  elementype = type;
85  }
86  else if( !_infaces.empty() )
87  {
88  EntityType type = mbImpl->type_from_handle( _infaces[0] );
89  if( type == MBPOLYGON ) MB_SET_ERR( MB_FAILURE, "Not supported 2D entity type: POLYGON" );
90 
91  meshdim = 2;
92  elementype = type;
93  }
94  else if( !_inedges.empty() )
95  {
96  meshdim = 1;
98  }
99  else
100  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Encountered a mixed-dimensional or invalid mesh" );
101 
102  // Initialize std::map to get indices of degrees.
103  deg_index[2] = 0;
104  deg_index[3] = 1;
105  deg_index[5] = 2;
106 
107  // Set ghost flag to false
108  hasghost = false;
109  return MB_SUCCESS;
110 }
111 
112 /************************************************************
113  * Interface Functions *
114  ************************************************************/
115 
117  int* level_degrees,
118  std::vector< EntityHandle >& level_sets,
119  bool optimize )
120 {
121  assert( num_level > 0 );
122  nlevels = num_level;
123 
125  std::vector< moab::EntityHandle > hmsets( num_level );
126 
127  if( meshdim <= 2 )
128  {
129  for( int i = 0; i < num_level; i++ )
130  {
131  assert( ( level_degrees[i] == 2 ) || ( level_degrees[i] == 3 ) || ( level_degrees[i] == 5 ) );
132  level_dsequence[i] = level_degrees[i];
133  }
134  }
135  else
136  {
137  for( int i = 0; i < num_level; i++ )
138  {
139  assert( ( level_degrees[i] == 2 ) || ( level_degrees[i] == 3 ) );
140  level_dsequence[i] = level_degrees[i];
141  }
142  }
143 
144  error = generate_hm( level_degrees, num_level, &hmsets[0], optimize );
145  MB_CHK_ERR( error );
146 
147  // copy the entity handles
148  level_sets.resize( num_level + 1 );
149  level_sets[0] = _rset;
150  for( int i = 0; i < num_level; i++ )
151  level_sets[i + 1] = hmsets[i];
152 
153  return MB_SUCCESS;
154 }
155 
156 ErrorCode NestedRefine::get_connectivity( EntityHandle ent, int level, std::vector< EntityHandle >& conn )
157 {
159  EntityType type = mbImpl->type_from_handle( ent );
160  EntityHandle start_ent;
161  if( !conn.empty() ) conn.clear();
162  if( level > 0 )
163  {
164  if( type == MBEDGE )
165  {
166  conn.reserve( 2 );
167  start_ent = level_mesh[level - 1].start_edge;
168  EntityID offset = ID_FROM_HANDLE( ent ) - ID_FROM_HANDLE( start_ent );
169  conn.push_back( level_mesh[level - 1].edge_conn[2 * offset] );
170  conn.push_back( level_mesh[level - 1].edge_conn[2 * offset + 1] );
171  }
172  else if( type == MBTRI || type == MBQUAD )
173  {
174  int num_corners = ahf->lConnMap2D[type - 2].num_verts_in_face;
175  conn.reserve( num_corners );
176  start_ent = level_mesh[level - 1].start_face;
177  EntityID offset = ID_FROM_HANDLE( ent ) - ID_FROM_HANDLE( start_ent );
178 
179  for( int i = 0; i < num_corners; i++ )
180  conn.push_back( level_mesh[level - 1].face_conn[num_corners * offset + i] );
181  }
182  else if( type == MBTET || type == MBHEX )
183  {
185  int num_corners = ahf->lConnMap3D[index].num_verts_in_cell;
186  conn.reserve( num_corners );
187  start_ent = level_mesh[level - 1].start_cell;
188  EntityID offset = ID_FROM_HANDLE( ent ) - ID_FROM_HANDLE( start_ent );
189  for( int i = 0; i < num_corners; i++ )
190  conn.push_back( level_mesh[level - 1].cell_conn[num_corners * offset + i] );
191  }
192  else
193  MB_SET_ERR( MB_FAILURE, "Requesting connectivity for an unsupported entity type" );
194  }
195  else
196  {
197  error = mbImpl->get_connectivity( &ent, 1, conn );
198  MB_CHK_ERR( error );
199  }
200 
201  return MB_SUCCESS;
202 }
203 
204 ErrorCode NestedRefine::get_coordinates( EntityHandle* verts, int num_verts, int level, double* coords )
205 {
206  if( level > 0 )
207  {
208  EntityID vstart = ID_FROM_HANDLE( level_mesh[level - 1].start_vertex );
209  for( int i = 0; i < num_verts; i++ )
210  {
211  const EntityHandle& vid = verts[i];
212  EntityID offset = ID_FROM_HANDLE( vid ) - vstart;
213  coords[3 * i] = level_mesh[level - 1].coordinates[0][offset];
214  coords[3 * i + 1] = level_mesh[level - 1].coordinates[1][offset];
215  coords[3 * i + 2] = level_mesh[level - 1].coordinates[2][offset];
216  }
217  }
218  else
219  {
221  error = mbImpl->get_coords( verts, num_verts, coords );
222  MB_CHK_ERR( error );
223  }
224 
225  return MB_SUCCESS;
226 }
227 
229  const unsigned int target_dimension,
230  std::vector< EntityHandle >& target_entities )
231 
232 {
234  error = ahf->get_adjacencies( source_entity, target_dimension, target_entities );
235  MB_CHK_ERR( error );
236 
237  return MB_SUCCESS;
238 }
239 
240 ErrorCode NestedRefine::child_to_parent( EntityHandle child, int child_level, int parent_level, EntityHandle* parent )
241 {
242  assert( ( child_level > 0 ) && ( child_level > parent_level ) );
243  EntityType type = mbImpl->type_from_handle( child );
244  assert( type != MBVERTEX );
245 
246  int child_index;
247  if( type == MBEDGE )
248  child_index = child - level_mesh[child_level - 1].start_edge;
249  else if( type == MBTRI || type == MBQUAD )
250  child_index = child - level_mesh[child_level - 1].start_face;
251  else if( type == MBTET || type == MBHEX )
252  child_index = child - level_mesh[child_level - 1].start_cell;
253  else
254  MB_SET_ERR( MB_FAILURE, "Requesting parent for unsupported entity type" );
255 
256  int parent_index;
257  int l = child_level - parent_level;
258  for( int i = 0; i < l; i++ )
259  {
260  int d = get_index_from_degree( level_dsequence[child_level - i - 1] );
261  int nch = refTemplates[type - 1][d].total_new_ents;
262  child_index = child_index / nch;
263  }
264  parent_index = child_index;
265 
266  if( type == MBEDGE )
267  {
268  if( parent_level > 0 )
269  *parent = level_mesh[parent_level - 1].start_edge + parent_index;
270  else
271  *parent = _inedges[parent_index];
272  }
273  else if( type == MBTRI || type == MBQUAD )
274  {
275  if( parent_level > 0 )
276  *parent = level_mesh[parent_level - 1].start_face + parent_index;
277  else
278  *parent = _infaces[parent_index];
279  }
280  else if( type == MBTET || type == MBHEX )
281  {
282  if( parent_level > 0 )
283  *parent = level_mesh[parent_level - 1].start_cell + parent_index;
284  else
285  *parent = _incells[parent_index];
286  }
287 
288  return MB_SUCCESS;
289 }
290 
292  int parent_level,
293  int child_level,
294  std::vector< EntityHandle >& children )
295 {
296  assert( ( child_level > 0 ) && ( child_level > parent_level ) );
297  EntityType type = mbImpl->type_from_handle( parent );
298  assert( type != MBVERTEX );
299 
300  int parent_index;
301  if( type == MBEDGE )
302  {
303  if( parent_level > 0 )
304  parent_index = parent - level_mesh[parent_level - 1].start_edge;
305  else
306  parent_index = _inedges.index( parent );
307  }
308  else if( type == MBTRI || type == MBQUAD )
309  {
310  if( parent_level > 0 )
311  parent_index = parent - level_mesh[parent_level - 1].start_face;
312  else
313  parent_index = _infaces.index( parent );
314  }
315  else if( type == MBTET || type == MBHEX )
316  {
317  if( parent_level > 0 )
318  parent_index = parent - level_mesh[parent_level - 1].start_cell;
319  else
320  parent_index = _incells.index( parent );
321  }
322  else
323  MB_SET_ERR( MB_FAILURE, "Requesting children for unsupported entity type" );
324 
325  int start, end;
326  start = end = parent_index;
327  for( int i = parent_level; i < child_level; i++ )
328  {
330  int nch = refTemplates[type - 1][d].total_new_ents;
331  start = start * nch;
332  end = end * nch + nch - 1;
333  }
334 
335  int num_child = end - start;
336  children.reserve( num_child );
337 
338  for( int i = start; i <= end; i++ )
339  {
340  EntityHandle child;
341  if( type == MBEDGE )
342  child = level_mesh[child_level - 1].start_edge + i;
343  else if( type == MBTRI || type == MBQUAD )
344  child = level_mesh[child_level - 1].start_face + i;
345  else if( type == MBTET || type == MBHEX )
346  child = level_mesh[child_level - 1].start_cell + i;
347 
348  children.push_back( child );
349  }
350 
351  return MB_SUCCESS;
352 }
353 
355  int vert_level,
356  int parent_level,
357  std::vector< EntityHandle >& incident_entities )
358 {
359  assert( vert_level > parent_level );
361 
362  // Step 1: Get the incident entities at the current level
363  std::vector< EntityHandle > inents;
364  if( meshdim == 1 )
365  {
366  error = ahf->get_up_adjacencies_1d( vertex, inents );
367  MB_CHK_ERR( error );
368  }
369  else if( meshdim == 2 )
370  {
372  MB_CHK_ERR( error );
373  }
374  else if( meshdim == 3 )
375  {
377  MB_CHK_ERR( error );
378  }
379 
380  // Step 2: Loop over all the incident entities at the current level and gather their parents
381  for( int i = 0; i < (int)inents.size(); i++ )
382  {
383  EntityHandle ent = inents[i];
384  EntityHandle parent;
385  error = child_to_parent( ent, vert_level, parent_level, &parent );
386  MB_CHK_ERR( error );
387  incident_entities.push_back( parent );
388  }
389 
390  // Step 3: Sort and remove duplicates
391  std::sort( incident_entities.begin(), incident_entities.end() );
392  incident_entities.erase( std::unique( incident_entities.begin(), incident_entities.end() ),
393  incident_entities.end() );
394 
395  return MB_SUCCESS;
396 }
397 
399  int vert_level,
400  int child_level,
401  std::vector< EntityHandle >& incident_entities )
402 {
403  assert( vert_level < child_level );
405 
406  // Step 1: Get the incident entities at the current level
407  std::vector< EntityHandle > inents;
408  if( meshdim == 1 )
409  {
410  error = ahf->get_up_adjacencies_1d( vertex, inents );
411  MB_CHK_ERR( error );
412  }
413  else if( meshdim == 2 )
414  {
416  MB_CHK_ERR( error );
417  }
418  else if( meshdim == 3 )
419  {
421  MB_CHK_ERR( error );
422  }
423 
424  // Step 2: Loop over all the incident entities at the current level and gather their parents
425  std::vector< EntityHandle > childs;
426  for( int i = 0; i < (int)inents.size(); i++ )
427  {
428  childs.clear();
429  EntityHandle ent = inents[i];
430  error = parent_to_child( ent, vert_level, child_level, childs );
431  MB_CHK_ERR( error );
432  for( int j = 0; j < (int)childs.size(); j++ )
433  incident_entities.push_back( childs[j] );
434  }
435 
436  return MB_SUCCESS;
437 }
438 
440 {
441  if( ( vertex - *_inverts.begin() ) > _inverts.size() )
442  MB_SET_ERR( MB_FAILURE, "Requesting duplicates for non-coarse vertices" );
443 
444  dupvertex = level_mesh[level - 1].start_vertex + ( vertex - *_inverts.begin() );
445 
446  return MB_SUCCESS;
447 }
448 
450 {
451  bool is_border = false;
452  EntityType type = mbImpl->type_from_handle( entity );
453 
454  if( type == MBVERTEX )
455  is_border = is_vertex_on_boundary( entity );
456  else if( type == MBEDGE )
457  is_border = is_edge_on_boundary( entity );
458  else if( type == MBTRI || type == MBQUAD )
459  is_border = is_face_on_boundary( entity );
460  else if( type == MBTET || type == MBHEX )
461  is_border = is_cell_on_boundary( entity );
462  else
463  MB_SET_ERR( MB_FAILURE, "Requesting boundary information for unsupported entity type" );
464 
465  return is_border;
466 }
467 
468 ErrorCode NestedRefine::exchange_ghosts( std::vector< EntityHandle >& lsets, int num_glayers )
469 {
471 
472  if( hasghost ) return MB_SUCCESS;
473 
474  hasghost = true;
475 #ifdef MOAB_HAVE_MPI
476  error = pcomm->exchange_ghost_cells( meshdim, 0, num_glayers, 0, true, false );
477  MB_CHK_ERR( error );
478  {
479  Range empty_range;
480  error = pcomm->exchange_tags( GLOBAL_ID_TAG_NAME, empty_range );
481  MB_CHK_ERR( error );
482  // error = pcomm->assign_global_ids(lsets[i], 0, 1, false, true, false);MB_CHK_ERR(error);
483  }
484 #else
485  MB_SET_ERR( MB_FAILURE, "Requesting ghost layers for a serial mesh" );
486 #endif
487 
488  Range* lverts = new Range[lsets.size()];
489  Range* lents = new Range[lsets.size()];
490  for( size_t i = 0; i < lsets.size(); i++ )
491  {
492  error = mbImpl->get_entities_by_dimension( lsets[i], meshdim, lents[i] );
493  MB_CHK_ERR( error );
494  error = mbImpl->get_connectivity( lents[i], lverts[i] );
495  MB_CHK_ERR( error );
496 
497  for( int gl = 0; gl < num_glayers; gl++ )
498  {
499  error = mbImpl->get_adjacencies( lverts[i], meshdim, false, lents[i], Interface::UNION );
500  MB_CHK_ERR( error );
501  error = mbImpl->get_connectivity( lents[i], lverts[i] );
502  MB_CHK_ERR( error );
503  }
504  }
505  for( size_t i = 0; i < lsets.size(); i++ )
506  {
507  error = mbImpl->add_entities( lsets[i], lverts[i] );
508  MB_CHK_ERR( error );
509  error = mbImpl->add_entities( lsets[i], lents[i] );
510  MB_CHK_ERR( error );
511  }
512 
513  delete[] lverts;
514  delete[] lents;
515  return MB_SUCCESS;
516 }
517 
519 {
520  assert( level > 0 && level < nlevels + 1 );
521 
523  std::vector< Tag > mtags( 3 );
524 
526  MB_CHK_ERR( error );
528  MB_CHK_ERR( error );
530  MB_CHK_ERR( error );
531 
532  for( int i = 0; i < 3; i++ )
533  {
534  // Gather sets of a particular tag
535  Range sets;
536  error = mbImpl->get_entities_by_type_and_tag( _rset, MBENTITYSET, &mtags[i], NULL, 1, sets );
537  MB_CHK_ERR( error );
538 
539  // Loop over all sets, gather entities in each set and add their children at all levels to
540  // the set
541  Range set_ents;
542  Range::iterator set_it;
543  std::vector< EntityHandle > childs;
544 
545  for( set_it = sets.begin(); set_it != sets.end(); ++set_it )
546  {
547  // Get the entities in the set, recursively
548  set_ents.clear();
549  childs.clear();
550  error = mbImpl->get_entities_by_handle( *set_it, set_ents, true );
551  MB_CHK_ERR( error );
552 
553  // Gather child entities at the input level
554  for( Range::iterator sit = set_ents.begin(); sit != set_ents.end(); sit++ )
555  {
556  EntityType type = mbImpl->type_from_handle( *sit );
557  if( type == MBVERTEX )
558  {
559  Range conn;
560  std::vector< EntityHandle > cents;
561  error = vertex_to_entities_down( *sit, 0, level, cents );
562  MB_CHK_ERR( error );
563  error = mbImpl->get_connectivity( &cents[0], (int)cents.size(), conn, true );
564  MB_CHK_ERR( error );
565  childs.insert( childs.end(), cents.begin(), cents.end() );
566  }
567  else
568  {
569  error = parent_to_child( *sit, 0, level, childs );
570  MB_CHK_ERR( error );
571  }
572 
573  std::sort( childs.begin(), childs.end() );
574  childs.erase( std::unique( childs.begin(), childs.end() ), childs.end() );
575 
576  // Add child entities to tagged sets
577  error = mbImpl->add_entities( *set_it, &childs[0], childs.size() );
578  MB_CHK_ERR( error );
579  }
580 
581  // Remove the coarse entities
582  error = mbImpl->remove_entities( *set_it, set_ents );
583  MB_CHK_ERR( error );
584 
585  // Add
586  error = mbImpl->add_entities( lset, &( *set_it ), 1 );
587  MB_CHK_ERR( error );
588  }
589  }
590  return MB_SUCCESS;
591 }
592 
593 /***********************************************
594  * Basic functionalities: generate HM *
595  ***********************************************/
596 
597 ErrorCode NestedRefine::estimate_hm_storage( EntityHandle set, int level_degree, int cur_level, int hmest[4] )
598 {
600 
601  // Obtain the size of input mesh.
602  int nverts_prev, nedges_prev, nfaces_prev, ncells_prev;
603  if( cur_level )
604  {
605  nverts_prev = level_mesh[cur_level - 1].num_verts;
606  nedges_prev = level_mesh[cur_level - 1].num_edges;
607  nfaces_prev = level_mesh[cur_level - 1].num_faces;
608  ncells_prev = level_mesh[cur_level - 1].num_cells;
609  }
610  else
611  {
612  nverts_prev = _inverts.size();
613  nedges_prev = _inedges.size();
614  nfaces_prev = _infaces.size();
615  ncells_prev = _incells.size();
616  }
617 
618  // Estimate mesh size of current level mesh.
619  int nedges = 0, nfaces = 0;
620  error = count_subentities( set, cur_level - 1, &nedges, &nfaces );
621  MB_CHK_ERR( error );
622 
623  int d = get_index_from_degree( level_degree );
624  int nverts = refTemplates[MBEDGE - 1][d].nv_edge * nedges;
625  hmest[0] = nverts_prev + nverts;
626  hmest[1] = nedges_prev * refTemplates[MBEDGE - 1][d].total_new_ents;
627  hmest[2] = 0;
628  hmest[3] = 0;
629 
630  int findex, cindex;
631  if( nfaces_prev != 0 )
632  {
633  EntityHandle start_face;
634  if( cur_level )
635  start_face = level_mesh[cur_level - 1].start_face;
636  else
637  start_face = *_infaces.begin();
638  findex = mbImpl->type_from_handle( start_face ) - 1;
639  hmest[2] = nfaces_prev * refTemplates[findex][d].total_new_ents;
640 
641  if( meshdim == 2 ) hmest[0] += refTemplates[findex][d].nv_face * nfaces_prev;
642 
643  if( meshdim == 3 ) hmest[1] += nfaces_prev * intFacEdg[findex - 1][d].nie;
644  }
645 
646  if( ncells_prev != 0 )
647  {
648  cindex = mbImpl->type_from_handle( *( _incells.begin() ) ) - 1;
649  hmest[3] = ncells_prev * refTemplates[cindex][d].total_new_ents;
650 
651  hmest[0] += refTemplates[cindex][d].nv_face * nfaces;
652  hmest[0] += refTemplates[cindex][d].nv_cell * ncells_prev;
653  }
654 
655  return MB_SUCCESS;
656 }
657 
659 {
660  // Obtain chunks of memory for the current level. Add them to a particular meshset.
661  EntityHandle set_handle;
662  ErrorCode error = mbImpl->create_meshset( MESHSET_SET, set_handle );
663  MB_CHK_SET_ERR( error, "Cannot create mesh for the current level" );
664  *set = set_handle;
665 
666  ReadUtilIface* read_iface;
667  error = mbImpl->query_interface( read_iface );
668  MB_CHK_ERR( error );
669 
670  // Vertices
671  error = read_iface->get_node_coords( 3, estL[0], 0, level_mesh[cur_level].start_vertex,
672  level_mesh[cur_level].coordinates );
673  MB_CHK_ERR( error );
674  level_mesh[cur_level].num_verts = estL[0];
675 
676  Range newverts( level_mesh[cur_level].start_vertex, level_mesh[cur_level].start_vertex + estL[0] - 1 );
677  error = mbImpl->add_entities( *set, newverts );
678  MB_CHK_ERR( error );
679  level_mesh[cur_level].verts = newverts;
680 
681  Tag gidtag;
683  MB_CHK_ERR( error );
684  error = read_iface->assign_ids( gidtag, newverts, level_mesh[cur_level].start_vertex );
685  MB_CHK_ERR( error );
686 
687  // Edges
688  if( estL[1] )
689  {
690  error = read_iface->get_element_connect( estL[1], 2, MBEDGE, 0, level_mesh[cur_level].start_edge,
691  level_mesh[cur_level].edge_conn );
692  MB_CHK_ERR( error );
693  level_mesh[cur_level].num_edges = estL[1];
694 
695  Range newedges( level_mesh[cur_level].start_edge, level_mesh[cur_level].start_edge + estL[1] - 1 );
696  error = mbImpl->add_entities( *set, newedges );
697  MB_CHK_ERR( error );
698  level_mesh[cur_level].edges = newedges;
699  }
700  else
701  level_mesh[cur_level].num_edges = 0;
702 
703  // Faces
704  if( estL[2] )
705  {
706  EntityType type = mbImpl->type_from_handle( *( _infaces.begin() ) );
707  int nvpf = ahf->lConnMap2D[type - 2].num_verts_in_face;
708  error = read_iface->get_element_connect( estL[2], nvpf, type, 0, level_mesh[cur_level].start_face,
709  level_mesh[cur_level].face_conn );
710  MB_CHK_ERR( error );
711  level_mesh[cur_level].num_faces = estL[2];
712 
713  Range newfaces( level_mesh[cur_level].start_face, level_mesh[cur_level].start_face + estL[2] - 1 );
714  error = mbImpl->add_entities( *set, newfaces );
715  MB_CHK_ERR( error );
716  level_mesh[cur_level].faces = newfaces;
717  }
718  else
719  level_mesh[cur_level].num_faces = 0;
720 
721  // Cells
722  if( estL[3] )
723  {
724  EntityType type = mbImpl->type_from_handle( *( _incells.begin() ) );
726  int nvpc = ahf->lConnMap3D[index].num_verts_in_cell;
727  error = read_iface->get_element_connect( estL[3], nvpc, type, 0, level_mesh[cur_level].start_cell,
728  level_mesh[cur_level].cell_conn );
729  MB_CHK_ERR( error );
730  level_mesh[cur_level].num_cells = estL[3];
731 
732  Range newcells( level_mesh[cur_level].start_cell, level_mesh[cur_level].start_cell + estL[3] - 1 );
733  error = mbImpl->add_entities( *set, newcells );
734  MB_CHK_ERR( error );
735  level_mesh[cur_level].cells = newcells;
736  }
737  else
738  level_mesh[cur_level].num_cells = 0;
739 
740  // Resize the ahf maps
741  error = ahf->resize_hf_maps( level_mesh[cur_level].start_vertex, level_mesh[cur_level].num_verts,
742  level_mesh[cur_level].start_edge, level_mesh[cur_level].num_edges,
743  level_mesh[cur_level].start_face, level_mesh[cur_level].num_faces,
744  level_mesh[cur_level].start_cell, level_mesh[cur_level].num_cells );
745  MB_CHK_ERR( error );
746 
747  error = ahf->update_entity_ranges( *set );
748  MB_CHK_ERR( error );
749 
750  // If the mesh type changes, then update the member variable in ahf to use the applicable
751  // adjacency matrix
752  MESHTYPE nwmesh = ahf->get_mesh_type( level_mesh[cur_level].num_verts, level_mesh[cur_level].num_edges,
753  level_mesh[cur_level].num_faces, level_mesh[cur_level].num_cells );
754  MB_CHK_ERR( error );
755  if( ahf->thismeshtype != nwmesh ) ahf->thismeshtype = nwmesh;
756 
757  return MB_SUCCESS;
758 }
759 
760 /**********************************
761  * Hierarchical Mesh Generation *
762  * *********************************/
763 
764 ErrorCode NestedRefine::generate_hm( int* level_degrees, int num_level, EntityHandle* hm_set, bool optimize )
765 {
767 
768  Tag gidtag;
770  MB_CHK_ERR( error );
771 
772  nlevels = num_level;
773 
774  timeall.tm_total = 0;
775  timeall.tm_refine = 0;
776  timeall.tm_resolve = 0;
777 
778  for( int l = 0; l < num_level; l++ )
779  {
780  double tstart;
781  tstart = tm->time_elapsed();
782 
783  // Estimate storage
784  int hmest[4] = { 0, 0, 0, 0 };
785  EntityHandle set;
786  if( l )
787  set = hm_set[l - 1];
788  else
789  set = _rset;
790  error = estimate_hm_storage( set, level_degrees[l], l, hmest );
791  MB_CHK_ERR( error );
792 
793  // Create arrays for storing the current level
794  error = create_hm_storage_single_level( &hm_set[l], l, hmest );
795  MB_CHK_ERR( error );
796 
797  // Copy the old vertices along with their coordinates
799  MB_CHK_ERR( error );
800 
801  // Create the new entities and new vertices
802  error = construct_hm_entities( l, level_degrees[l] );
803  MB_CHK_ERR( error );
804 
805  timeall.tm_refine += tm->time_elapsed() - tstart;
806 
807  // Go into parallel communication
808  if( !optimize )
809  {
810 #ifdef MOAB_HAVE_MPI
811  if( pcomm && ( pcomm->size() > 1 ) )
812  {
813  double tpstart = tm->time_elapsed();
814  error = resolve_shared_ents_parmerge( l, hm_set[l] );
815  MB_CHK_ERR( error );
816  timeall.tm_resolve += tm->time_elapsed() - tpstart;
817  }
818 #endif
819  }
820  }
821 
822  if( optimize )
823  {
824 #ifdef MOAB_HAVE_MPI
825  if( pcomm && ( pcomm->size() > 1 ) )
826  {
827  double tpstart = tm->time_elapsed();
828  error = resolve_shared_ents_opt( hm_set, nlevels );
829  MB_CHK_ERR( error );
830  timeall.tm_resolve = tm->time_elapsed() - tpstart;
831  }
832 #endif
833  }
835 
836  return MB_SUCCESS;
837 }
838 
840 {
842 
843  // Generate mesh for current level by refining previous level.
844  if( ahf->thismeshtype == CURVE )
845  {
846  error = construct_hm_1D( cur_level, deg );
847  MB_CHK_ERR( error );
848  }
849  else if( ahf->thismeshtype == SURFACE || ahf->thismeshtype == SURFACE_MIXED )
850  {
851  error = construct_hm_2D( cur_level, deg );
852  MB_CHK_ERR( error );
853  }
854  else
855  {
856  error = construct_hm_3D( cur_level, deg );
857  MB_CHK_ERR( error );
858  }
859 
860  return MB_SUCCESS;
861 }
862 
863 ErrorCode NestedRefine::construct_hm_1D( int cur_level, int deg )
864 {
866  int nverts_prev, nents_prev;
867  if( cur_level )
868  {
869  nverts_prev = level_mesh[cur_level - 1].num_verts;
870  nents_prev = level_mesh[cur_level - 1].num_edges;
871  }
872  else
873  {
874  nverts_prev = _inverts.size();
875  nents_prev = _inedges.size();
876  }
877 
878  int d = get_index_from_degree( deg );
879  int vtotal = 2 + refTemplates[0][d].total_new_verts;
880  std::vector< EntityHandle > vbuffer( vtotal );
881 
882  std::vector< EntityHandle > conn;
883  int count_nents = 0;
884  int count_verts = nverts_prev;
885 
886  // Step 1: Create the subentities via refinement of the previous mesh
887  for( int eid = 0; eid < nents_prev; eid++ )
888  {
889  conn.clear();
890 
891  // EntityHandle of the working edge
893  if( cur_level )
894  edge = level_mesh[cur_level - 1].start_edge + eid;
895  else
896  edge = _inedges[eid]; // Makes the assumption initial mesh is contiguous in memory
897 
898  error = get_connectivity( edge, cur_level, conn );
899  MB_CHK_ERR( error );
900 
901  // Add the vertex handles to vbuffer for the current level for the working edge
902 
903  // Since the old vertices are copied first, their local indices do not change as new levels
904  // are added. Clearly the local indices of the new vertices introduced in the current level
905  // is still the same when the old vertices are copied. Thus, there is no need to explicitly
906  // store another map between the old and duplicates in the subsequent levels. The second
907  // part in the following sum is the local index in the previous level.
908 
909  // Add the corners to the vbuffer first.
910 
911  for( int i = 0; i < (int)conn.size(); i++ )
912  {
913  if( cur_level )
914  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - level_mesh[cur_level - 1].start_vertex );
915  else
916  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - *_inverts.begin() );
917  }
918 
919  // Adding rest of the entityhandles to working buffer for vertices.
920  int num_new_verts = refTemplates[0][d].total_new_verts;
921 
922  for( int i = 0; i < num_new_verts; i++ )
923  {
924  vbuffer[i + 2] = level_mesh[cur_level].start_vertex + count_verts;
925  count_verts += 1;
926  }
927 
928  // Use the template to obtain the subentities
929  int id1, id2;
930  int etotal = refTemplates[0][d].total_new_ents;
931  std::vector< EntityHandle > ent_buffer( etotal );
932 
933  for( int i = 0; i < etotal; i++ )
934  {
935  id1 = refTemplates[0][d].ents_conn[i][0];
936  id2 = refTemplates[0][d].ents_conn[i][1];
937  level_mesh[cur_level].edge_conn[2 * ( count_nents )] = vbuffer[id1];
938  level_mesh[cur_level].edge_conn[2 * ( count_nents ) + 1] = vbuffer[id2];
939  ent_buffer[i] = level_mesh[cur_level].start_edge + count_nents;
940  count_nents += 1;
941  };
942 
943  error = update_local_ahf( deg, MBEDGE, &vbuffer[0], &ent_buffer[0], etotal );
944  MB_CHK_ERR( error );
945 
946  // Compute the coordinates of the new vertices: Linear interpolation
947  int idx;
948  double xi;
949  for( int i = 0; i < num_new_verts; i++ )
950  {
951  xi = refTemplates[0][d].vert_nat_coord[i][0];
952  idx = vbuffer[i + 2] - level_mesh[cur_level].start_vertex; // index of new vertex in current level
953  if( cur_level )
954  {
955  id1 = conn[0] - level_mesh[cur_level - 1].start_vertex; // index of old end vertices in current level
956  id2 = conn[1] - level_mesh[cur_level - 1].start_vertex;
957  }
958  else
959  {
960  id1 = _inverts.index( conn[0] );
961  id2 = _inverts.index( conn[1] );
962  }
963 
964  level_mesh[cur_level].coordinates[0][idx] =
965  ( 1 - xi ) * level_mesh[cur_level].coordinates[0][id1] + xi * level_mesh[cur_level].coordinates[0][id2];
966  level_mesh[cur_level].coordinates[1][idx] =
967  ( 1 - xi ) * level_mesh[cur_level].coordinates[1][id1] + xi * level_mesh[cur_level].coordinates[1][id2];
968  level_mesh[cur_level].coordinates[2][idx] =
969  ( 1 - xi ) * level_mesh[cur_level].coordinates[2][id1] + xi * level_mesh[cur_level].coordinates[2][id2];
970  }
971  }
972 
973  error = update_global_ahf( MBEDGE, cur_level, deg );
974  MB_CHK_ERR( error );
975 
976  return MB_SUCCESS;
977 }
978 
980  int deg,
981  EntityType type,
982  std::vector< EntityHandle >& trackverts )
983 {
985 
986  int nedges_prev;
987  if( cur_level )
988  nedges_prev = level_mesh[cur_level - 1].num_edges;
989  else
990  nedges_prev = _inedges.size();
991 
992  int d = get_index_from_degree( deg );
993  int nve = refTemplates[0][d].nv_edge;
994  int vtotal = 2 + refTemplates[0][d].total_new_verts;
995  int etotal = refTemplates[0][d].total_new_ents;
996  int ne = 0, dim = 0, index = 0;
997  if( type == MBTRI || type == MBQUAD )
998  {
999  index = type - 2;
1001  dim = 2;
1002  }
1003  else if( type == MBTET || type == MBHEX )
1004  {
1005  index = ahf->get_index_in_lmap( *( _incells.begin() ) );
1007  dim = 3;
1008  }
1009 
1010  std::vector< EntityHandle > vbuffer( vtotal );
1011  std::vector< EntityHandle > ent_buffer( etotal );
1012 
1013  std::vector< EntityHandle > adjents, econn, fconn;
1014  std::vector< int > leids;
1015  int count_nents = 0;
1016 
1017  // Loop over all the edges and gather the vertices to be used for refinement
1018  for( int eid = 0; eid < nedges_prev; eid++ )
1019  {
1020  adjents.clear();
1021  leids.clear();
1022  econn.clear();
1023  fconn.clear();
1024  for( int i = 0; i < vtotal; i++ )
1025  vbuffer[i] = 0;
1026  for( int i = 0; i < etotal; i++ )
1027  ent_buffer[i] = 0;
1028 
1030  if( cur_level )
1031  edge = level_mesh[cur_level - 1].start_edge + eid;
1032  else
1033  edge = _inedges[eid];
1034 
1035  error = get_connectivity( edge, cur_level, econn );
1036  MB_CHK_ERR( error );
1037 
1038  for( int i = 0; i < (int)econn.size(); i++ )
1039  {
1040  if( cur_level )
1041  vbuffer[i] = level_mesh[cur_level].start_vertex + ( econn[i] - level_mesh[cur_level - 1].start_vertex );
1042  else
1043  vbuffer[i] = level_mesh[cur_level].start_vertex + ( econn[i] - *_inverts.begin() );
1044  }
1045 
1046  int fid = -1, lid = -1, idx1 = -1, idx2 = -1;
1047 
1048  if( dim == 2 )
1049  {
1050  error = ahf->get_up_adjacencies_2d( edge, adjents, &leids );
1051  MB_CHK_ERR( error );
1052  if( cur_level )
1053  fid = adjents[0] - level_mesh[cur_level - 1].start_face;
1054  else
1055  fid = _infaces.index( adjents[0] );
1056 
1057  lid = leids[0];
1058  idx1 = lid;
1059  idx2 = ahf->lConnMap2D[index].next[lid];
1060  }
1061  else if( dim == 3 )
1062  {
1063  error = ahf->get_up_adjacencies_edg_3d( edge, adjents, &leids );
1064  MB_CHK_ERR( error );
1065  if( cur_level )
1066  fid = adjents[0] - level_mesh[cur_level - 1].start_cell;
1067  else
1068  fid = _incells.index( adjents[0] );
1069 
1070  lid = leids[0];
1071  idx1 = ahf->lConnMap3D[index].e2v[lid][0];
1072  idx2 = ahf->lConnMap3D[index].e2v[lid][1];
1073  }
1074 
1075  error = get_connectivity( adjents[0], cur_level, fconn );
1076  MB_CHK_ERR( error );
1077 
1078  bool orient = false;
1079  if( ( fconn[idx1] == econn[0] ) && ( fconn[idx2] == econn[1] ) ) orient = true;
1080 
1081  if( orient )
1082  {
1083  for( int j = 0; j < nve; j++ )
1084  vbuffer[j + 2] = trackverts[fid * ne * nve + nve * lid + j];
1085  }
1086  else
1087  {
1088  for( int j = 0; j < nve; j++ )
1089  vbuffer[( nve - j - 1 ) + 2] = trackverts[fid * ne * nve + nve * lid + j];
1090  }
1091 
1092  // Use the template to obtain the subentities
1093  int id1, id2;
1094 
1095  for( int i = 0; i < etotal; i++ )
1096  {
1097  id1 = refTemplates[0][d].ents_conn[i][0];
1098  id2 = refTemplates[0][d].ents_conn[i][1];
1099  level_mesh[cur_level].edge_conn[2 * ( count_nents )] = vbuffer[id1];
1100  level_mesh[cur_level].edge_conn[2 * ( count_nents ) + 1] = vbuffer[id2];
1101  ent_buffer[i] = level_mesh[cur_level].start_edge + count_nents;
1102 
1103  count_nents += 1;
1104  };
1105 
1106  error = update_local_ahf( deg, MBEDGE, &vbuffer[0], &ent_buffer[0], etotal );
1107  MB_CHK_ERR( error );
1108  }
1109 
1110  error = update_global_ahf_1D_sub( cur_level, deg );
1111  MB_CHK_ERR( error );
1112 
1113  return MB_SUCCESS;
1114 }
1115 
1116 ErrorCode NestedRefine::construct_hm_2D( int cur_level, int deg )
1117 {
1118  ErrorCode error;
1119  int nverts_prev, nents_prev;
1120  if( cur_level )
1121  {
1122  nverts_prev = level_mesh[cur_level - 1].num_verts;
1123  nents_prev = level_mesh[cur_level - 1].num_faces;
1124  }
1125  else
1126  {
1127  nverts_prev = _inverts.size();
1128  nents_prev = _infaces.size();
1129  }
1130 
1131  // Create some book-keeping arrays over the old mesh to avoid introducing duplicate vertices and
1132  // calculating vertices more than once.
1133  EntityType ftype = mbImpl->type_from_handle( *_infaces.begin() );
1134  int nepf = ahf->lConnMap2D[ftype - 2].num_verts_in_face;
1135  int findex = ftype - 1;
1136 
1137  int d = get_index_from_degree( deg );
1138  int tnv = refTemplates[findex][d].total_new_verts;
1139  int vtotal = nepf + tnv;
1140  std::vector< EntityHandle > vbuffer( vtotal );
1141  int etotal = refTemplates[findex][d].total_new_ents;
1142  std::vector< EntityHandle > ent_buffer( etotal );
1143 
1144  int nve = refTemplates[findex][d].nv_edge;
1145  std::vector< EntityHandle > trackvertsF( nents_prev * nepf * nve, 0 );
1146  int cur_nverts = level_mesh[cur_level].num_verts;
1147  std::vector< int > flag_verts( cur_nverts - nverts_prev, 0 );
1148 
1149  int count_nverts = nverts_prev;
1150  int count_nents = 0;
1151  std::vector< EntityHandle > conn, cur_conn;
1152 
1153  // Step 1: Create the subentities via refinement of the previous mesh
1154  for( int fid = 0; fid < nents_prev; fid++ )
1155  {
1156  conn.clear();
1157  cur_conn.clear();
1158  for( int i = 0; i < vtotal; i++ )
1159  vbuffer[i] = 0;
1160  for( int i = 0; i < etotal; i++ )
1161  ent_buffer[i] = 0;
1162 
1163  // EntityHandle of the working face
1165  if( cur_level )
1166  face = level_mesh[cur_level - 1].start_face + fid;
1167  else
1168  face = _infaces[fid];
1169 
1170  error = get_connectivity( face, cur_level, conn );
1171  MB_CHK_ERR( error );
1172 
1173  // Step 1: Add vertices from the current level for the working face that will be used for
1174  // subdivision.
1175  // Add the corners to vbuffer
1176  for( int i = 0; i < (int)conn.size(); i++ )
1177  {
1178  if( cur_level )
1179  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - level_mesh[cur_level - 1].start_vertex );
1180  else
1181  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - *_inverts.begin() );
1182 
1183  cur_conn.push_back( vbuffer[i] );
1184  }
1185 
1186  // Gather vertices already added to tracking array due to refinement of the sibling faces
1187 
1188  for( int i = 0; i < nepf; i++ )
1189  {
1190  for( int j = 0; j < nve; j++ )
1191  {
1192  int id = refTemplates[findex][d].vert_on_edges[i][j];
1193  vbuffer[id] = trackvertsF[fid * nve * nepf + nve * i + j];
1194  }
1195  }
1196 
1197  // Add the remaining vertex handles to vbuffer for the current level for the working face
1198  for( int i = 0; i < tnv; i++ )
1199  {
1200  if( !vbuffer[i + nepf] )
1201  {
1202  vbuffer[i + nepf] = level_mesh[cur_level].start_vertex + count_nverts;
1203  count_nverts += 1;
1204  }
1205  }
1206 
1207  // Step 2: Create the subentities using the template and the vbuffer
1208  int idx;
1209  for( int i = 0; i < etotal; i++ )
1210  {
1211  for( int k = 0; k < nepf; k++ )
1212  {
1213  idx = refTemplates[findex][d].ents_conn[i][k];
1214  level_mesh[cur_level].face_conn[nepf * count_nents + k] = vbuffer[idx];
1215  }
1216  ent_buffer[i] = level_mesh[cur_level].start_face + count_nents;
1217  count_nents += 1;
1218  }
1219 
1220  // Step 3: Update the local AHF maps
1221  error = update_local_ahf( deg, ftype, &vbuffer[0], &ent_buffer[0], etotal );
1222  MB_CHK_ERR( error );
1223 
1224  // Step 4: Add the new vertices to the tracking array
1225  int id;
1226 
1227  for( int i = 0; i < nepf; i++ )
1228  {
1229  // Add the vertices to trackvertsF for fid
1230  for( int j = 0; j < nve; j++ )
1231  {
1232  id = refTemplates[findex][d].vert_on_edges[i][j];
1233  trackvertsF[fid * nepf * nve + nve * i + j] = vbuffer[id];
1234  }
1235 
1236  std::vector< EntityHandle > sibfids;
1237  std::vector< int > sibleids;
1238  std::vector< int > siborient;
1239 
1240  // Add the vertices to trackvertsF for siblings of fid, if any.
1241  error = ahf->get_up_adjacencies_2d( face, i, false, sibfids, &sibleids, &siborient );
1242  MB_CHK_ERR( error );
1243 
1244  if( !sibfids.size() ) continue;
1245 
1246  for( int s = 0; s < (int)sibfids.size(); s++ )
1247  {
1248  int sibid;
1249  if( cur_level )
1250  sibid = sibfids[s] - level_mesh[cur_level - 1].start_face;
1251  else
1252  sibid = sibfids[s] - *_infaces.begin();
1253 
1254  if( siborient[s] ) // Same half-edge direction as the current half-edge
1255  {
1256  for( int j = 0; j < nve; j++ )
1257  {
1258  id = refTemplates[findex][d].vert_on_edges[i][j];
1259  trackvertsF[sibid * nepf * nve + nve * sibleids[s] + j] = vbuffer[id];
1260  }
1261  }
1262  else
1263  {
1264  for( int j = 0; j < nve; j++ )
1265  {
1266  id = refTemplates[findex][d].vert_on_edges[i][nve - j - 1];
1267  trackvertsF[sibid * nepf * nve + nve * sibleids[s] + j] = vbuffer[id];
1268  }
1269  }
1270  }
1271  }
1272 
1273  // Step 5: Compute the coordinates of the new vertices, avoids computing more than once via
1274  // the flag_verts array.
1275  std::vector< double > corner_coords( nepf * 3 );
1276  error = get_coordinates( &cur_conn[0], nepf, cur_level + 1, &corner_coords[0] );
1277  MB_CHK_ERR( error );
1278 
1279  error = compute_coordinates( cur_level, deg, ftype, &vbuffer[0], vtotal, &corner_coords[0], flag_verts,
1280  nverts_prev );
1281  MB_CHK_ERR( error );
1282  }
1283 
1284  // Step 6: Update the global maps
1285  error = update_global_ahf( ftype, cur_level, deg );
1286  MB_CHK_ERR( error );
1287 
1288  // Step 7: If edges exists, refine them.
1289  if( !_inedges.empty() )
1290  {
1291  error = construct_hm_1D( cur_level, deg, ftype, trackvertsF );
1292  MB_CHK_ERR( error );
1293  }
1294 
1295  return MB_SUCCESS;
1296 }
1297 
1299  int deg,
1300  EntityType type,
1301  std::vector< EntityHandle >& trackvertsE,
1302  std::vector< EntityHandle >& trackvertsF )
1303 {
1304  ErrorCode error;
1305 
1306  EntityType ftype = MBTRI;
1307  if( type == MBHEX ) ftype = MBQUAD;
1308 
1309  int d = get_index_from_degree( deg );
1310  int findex = ftype - 1;
1311  int cidx = ahf->get_index_in_lmap( *( _incells.begin() ) );
1312 
1313  int nepf = ahf->lConnMap2D[ftype - 2].num_verts_in_face;
1314  int nepc = ahf->lConnMap3D[cidx].num_edges_in_cell;
1315  int nfpc = ahf->lConnMap3D[cidx].num_faces_in_cell;
1316 
1317  int tnv = refTemplates[findex][d].total_new_verts;
1318  int nve = refTemplates[findex][d].nv_edge;
1319  int nvf = refTemplates[findex][d].nv_face;
1320  int vtotal = nepf + tnv;
1321  int etotal = refTemplates[findex][d].total_new_ents;
1322 
1323  std::vector< EntityHandle > vbuffer( vtotal );
1324  std::vector< EntityHandle > ent_buffer( etotal );
1325 
1326  std::vector< EntityHandle > adjents, fconn, cconn;
1327  std::vector< int > leids;
1328  int count_nents = 0;
1329 
1330  int nents_prev, ecount;
1331  if( cur_level )
1332  {
1333  nents_prev = level_mesh[cur_level - 1].num_faces;
1334  ecount = level_mesh[cur_level - 1].num_edges * refTemplates[MBEDGE - 1][d].total_new_ents;
1335  ;
1336  }
1337  else
1338  {
1339  nents_prev = _infaces.size();
1340  ecount = _inedges.size() * refTemplates[MBEDGE - 1][d].total_new_ents;
1341  ;
1342  }
1343 
1344  // Step 1: Create the subentities via refinement of the previous mesh
1345  for( int it = 0; it < nents_prev; it++ )
1346  {
1347  fconn.clear();
1348  cconn.clear();
1349  adjents.clear();
1350  leids.clear();
1351  for( int i = 0; i < vtotal; i++ )
1352  vbuffer[i] = 0;
1353  for( int i = 0; i < etotal; i++ )
1354  ent_buffer[i] = 0;
1355 
1356  // EntityHandle of the working face
1358  if( cur_level )
1359  face = level_mesh[cur_level - 1].start_face + it;
1360  else
1361  face = _infaces[it];
1362 
1363  error = get_connectivity( face, cur_level, fconn );
1364  MB_CHK_ERR( error );
1365 
1366  // Add the new handles for old connectivity in the buffer
1367  for( int i = 0; i < (int)fconn.size(); i++ )
1368  {
1369  if( cur_level )
1370  vbuffer[i] = level_mesh[cur_level].start_vertex + ( fconn[i] - level_mesh[cur_level - 1].start_vertex );
1371  else
1372  vbuffer[i] = level_mesh[cur_level].start_vertex + ( fconn[i] - *_inverts.begin() );
1373  }
1374 
1375  // Add handles for vertices on edges and faces from the already refined cell
1376  int fid, lid;
1377  error = ahf->get_up_adjacencies_face_3d( face, adjents, &leids );
1378  MB_CHK_ERR( error );
1379 
1380  if( cur_level )
1381  fid = adjents[0] - level_mesh[cur_level - 1].start_cell;
1382  else
1383  fid = _incells.index( adjents[0] );
1384 
1385  lid = leids[0];
1386 
1387  error = get_connectivity( adjents[0], cur_level, cconn );
1388  MB_CHK_ERR( error );
1389 
1390  // Find the orientation w.r.t the half-face and then add vertices properly.
1391  std::vector< EntityHandle > fac_conn( nepf );
1392  std::vector< EntityHandle > lfac_conn( nepf );
1393  for( int j = 0; j < nepf; j++ )
1394  {
1395  fac_conn[j] = fconn[j];
1396  int id = ahf->lConnMap3D[cidx].hf2v[lid][j];
1397  lfac_conn[j] = cconn[id];
1398  }
1399 
1400  std::vector< int > le_idx, indices;
1401 
1402  error = reorder_indices( deg, &fac_conn[0], &lfac_conn[0], nepf, le_idx, indices );
1403  MB_CHK_ERR( error );
1404 
1405  // Add the existing vertices on edges of the already refined cell to the vbuffer
1406  for( int j = 0; j < nepf; j++ )
1407  {
1408  int id = le_idx[j]; // Corresponding local edge
1409  int idx = ahf->lConnMap3D[cidx].f2leid[lid][id]; // Local edge in the cell
1410 
1411  // Get the orientation of the local edge of the face wrt the corresponding local edge in
1412  // the cell
1413  bool eorient = false;
1414  int fnext = ahf->lConnMap2D[ftype - 2].next[j];
1415  int idx1 = ahf->lConnMap3D[cidx].e2v[idx][0];
1416  int idx2 = ahf->lConnMap3D[cidx].e2v[idx][1];
1417  if( ( fconn[j] == cconn[idx1] ) && ( fconn[fnext] == cconn[idx2] ) ) eorient = true;
1418 
1419  if( eorient )
1420  {
1421  for( int k = 0; k < nve; k++ )
1422  {
1423  int ind = refTemplates[findex][d].vert_on_edges[j][k];
1424  vbuffer[ind] = trackvertsE[fid * nepc * nve + nve * idx + k];
1425  }
1426  }
1427  else
1428  {
1429  for( int k = 0; k < nve; k++ )
1430  {
1431  int ind = refTemplates[findex][d].vert_on_edges[j][nve - k - 1];
1432  vbuffer[ind] = trackvertsE[fid * nepc * nve + nve * idx + k];
1433  }
1434  }
1435  }
1436 
1437  // Add the existing vertices on the face of the refine cell to vbuffer
1438  if( nvf )
1439  {
1440  for( int k = 0; k < nvf; k++ )
1441  {
1442  int ind = refTemplates[findex][d].vert_on_faces[0][k];
1443  vbuffer[ind] = trackvertsF[fid * nfpc * nvf + nvf * lid + indices[k] - 1];
1444  }
1445  }
1446 
1447  // Create the subentities using the template and the vbuffer
1448  for( int i = 0; i < etotal; i++ )
1449  {
1450  for( int k = 0; k < nepf; k++ )
1451  {
1452  int idx = refTemplates[findex][d].ents_conn[i][k];
1453  level_mesh[cur_level].face_conn[nepf * count_nents + k] = vbuffer[idx];
1454  }
1455  ent_buffer[i] = level_mesh[cur_level].start_face + count_nents;
1456  count_nents += 1;
1457  }
1458 
1459  error = update_local_ahf( deg, ftype, &vbuffer[0], &ent_buffer[0], etotal );
1460  MB_CHK_ERR( error );
1461 
1462  // Create the interior edges
1463  int id1, id2;
1464 
1465  int ne = intFacEdg[ftype - 2][d].nie;
1466  for( int i = 0; i < ne; i++ )
1467  {
1468  id1 = intFacEdg[ftype - 2][d].ieconn[i][0];
1469  id2 = intFacEdg[ftype - 2][d].ieconn[i][1];
1470  level_mesh[cur_level].edge_conn[2 * ( ecount )] = vbuffer[id1];
1471  level_mesh[cur_level].edge_conn[2 * ( ecount ) + 1] = vbuffer[id2];
1472  ecount += 1;
1473  }
1474  }
1475 
1476  // Step 6: Update the global maps
1477  error = update_global_ahf_2D_sub( cur_level, deg );
1478  MB_CHK_ERR( error );
1479 
1480  // Step 7: Update the hf-maps for the edges
1481  error = update_ahf_1D( cur_level );
1482  MB_CHK_ERR( error );
1483 
1484  return MB_SUCCESS;
1485 }
1486 
1487 ErrorCode NestedRefine::construct_hm_3D( int cur_level, int deg )
1488 {
1489  ErrorCode error;
1490  EntityType type = mbImpl->type_from_handle( *( _incells.begin() ) );
1491  if( type == MBTET )
1492  {
1493  error = subdivide_tets( cur_level, deg );
1494  MB_CHK_ERR( error );
1495  }
1496  else
1497  {
1498  error = subdivide_cells( type, cur_level, deg );
1499  MB_CHK_ERR( error );
1500  }
1501 
1502  return MB_SUCCESS;
1503 }
1504 
1505 ErrorCode NestedRefine::subdivide_cells( EntityType type, int cur_level, int deg )
1506 {
1507  ErrorCode error;
1508  int nverts_prev, nents_prev;
1509  if( cur_level )
1510  {
1511  nverts_prev = level_mesh[cur_level - 1].num_verts;
1512  nents_prev = level_mesh[cur_level - 1].num_cells;
1513  }
1514  else
1515  {
1516  nverts_prev = _inverts.size();
1517  nents_prev = _incells.size();
1518  }
1519 
1520  // Create some book-keeping arrays over the parent mesh to avoid introducing duplicate vertices
1521  int cindex = type - 1;
1522  int d = get_index_from_degree( deg );
1523  int ne = refTemplates[cindex][d].nv_edge;
1524  int nvf = refTemplates[cindex][d].nv_face;
1525  int nvtotal = refTemplates[cindex][d].total_new_verts;
1526 
1527  int index = ahf->get_index_in_lmap( *( _incells.begin() ) );
1528  int nvpc = ahf->lConnMap3D[index].num_verts_in_cell;
1529  int nepc = ahf->lConnMap3D[index].num_edges_in_cell;
1530  int nfpc = ahf->lConnMap3D[index].num_faces_in_cell;
1531 
1532  int vtotal = nvpc + nvtotal;
1533  std::vector< EntityHandle > vbuffer( vtotal );
1534 
1535  std::vector< EntityHandle > trackvertsC_edg( nepc * ne * nents_prev, 0 );
1536  std::vector< EntityHandle > trackvertsC_face( nfpc * nvf * nents_prev, 0 );
1537 
1538  int cur_nverts = level_mesh[cur_level].num_verts;
1539  std::vector< int > flag_verts( cur_nverts - nverts_prev, 0 );
1540 
1541  int count_nverts = nverts_prev;
1542  int count_ents = 0;
1543  std::vector< EntityHandle > conn, cur_conn;
1544 
1545  // Step 1: Create the subentities via refinement of the previous mesh
1546  for( int cid = 0; cid < nents_prev; cid++ )
1547  {
1548  conn.clear();
1549  cur_conn.clear();
1550  for( int i = 0; i < vtotal; i++ )
1551  vbuffer[i] = 0;
1552 
1553  // EntityHandle of the working cell
1554  EntityHandle cell;
1555  if( cur_level )
1556  cell = level_mesh[cur_level - 1].start_cell + cid;
1557  else
1558  cell = _incells[cid];
1559 
1560  error = get_connectivity( cell, cur_level, conn );
1561  MB_CHK_ERR( error );
1562 
1563  // Step 1: Add vertices from the current level for the working face that will be used for
1564  // subdivision.
1565  // Add the corners to vbuffer
1566  for( int i = 0; i < (int)conn.size(); i++ )
1567  {
1568  if( cur_level )
1569  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - level_mesh[cur_level - 1].start_vertex );
1570  else
1571  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - *_inverts.begin() );
1572 
1573  cur_conn.push_back( vbuffer[i] );
1574  }
1575 
1576  // Gather vertices already added to tracking array due to refinement of the sibling cells
1577  for( int i = 0; i < nepc; i++ )
1578  {
1579  for( int j = 0; j < ne; j++ )
1580  {
1581  int idx = refTemplates[cindex][d].vert_on_edges[i][j];
1582  vbuffer[idx] = trackvertsC_edg[cid * nepc * ne + ne * i + j];
1583  }
1584  }
1585 
1586  // Add remaining new vertex handles
1587  for( int i = 0; i < nfpc; i++ )
1588  {
1589  for( int j = 0; j < nvf; j++ )
1590  {
1591  int idx = refTemplates[cindex][d].vert_on_faces[i][j];
1592  vbuffer[idx] = trackvertsC_face[cid * nfpc * nvf + nvf * i + j];
1593  }
1594  }
1595 
1596  // Add the remaining vertex handles to vbuffer for the current level for the working cell
1597  for( int i = 0; i < nvtotal; i++ )
1598  {
1599  if( !vbuffer[i + nvpc] )
1600  {
1601  vbuffer[i + nvpc] = level_mesh[cur_level].start_vertex + count_nverts;
1602  count_nverts += 1;
1603  }
1604  }
1605 
1606  // Step 2: Use the template to obtain the subentities. The coordinates and local ahf maps
1607  // are also constructed. Connectivity of the children
1608  int etotal = refTemplates[type - 1][d].total_new_ents;
1609  std::vector< EntityHandle > ent_buffer( etotal );
1610 
1611  for( int i = 0; i < etotal; i++ )
1612  {
1613  for( int k = 0; k < nvpc; k++ )
1614  {
1615  int idx = refTemplates[type - 1][d].ents_conn[i][k];
1616  level_mesh[cur_level].cell_conn[nvpc * count_ents + k] = vbuffer[idx];
1617  }
1618  ent_buffer[i] = level_mesh[cur_level].start_cell + count_ents;
1619  count_ents += 1;
1620  }
1621 
1622  // Step 3: Update local ahf maps
1623  error = update_local_ahf( deg, type, &vbuffer[0], &ent_buffer[0], etotal );
1624  MB_CHK_ERR( error );
1625 
1626  // Step 4: Update tracking information
1627  error = update_tracking_verts( cell, cur_level, deg, trackvertsC_edg, trackvertsC_face, &vbuffer[0] );
1628  MB_CHK_ERR( error );
1629 
1630  // Step 5: Coordinates of the new vertices
1631  std::vector< double > corner_coords( nvpc * 3 );
1632  error = get_coordinates( &cur_conn[0], nvpc, cur_level + 1, &corner_coords[0] );
1633  MB_CHK_ERR( error );
1634 
1635  error = compute_coordinates( cur_level, deg, type, &vbuffer[0], vtotal, &corner_coords[0], flag_verts,
1636  nverts_prev );
1637  MB_CHK_ERR( error );
1638  }
1639 
1640  // error = ahf->print_tags(3);
1641 
1642  // Step 6: Update the global maps
1643  error = update_global_ahf( type, cur_level, deg );
1644  MB_CHK_ERR( error );
1645 
1646  // Step 7: If edges exists, refine them as well.
1647  if( level_mesh[cur_level].num_edges != 0 )
1648  {
1649  error = construct_hm_1D( cur_level, deg, type, trackvertsC_edg );
1650  MB_CHK_ERR( error );
1651  }
1652 
1653  // Step 8: If faces exists, refine them as well.
1654  if( !_infaces.empty() )
1655  {
1656  error = construct_hm_2D( cur_level, deg, type, trackvertsC_edg, trackvertsC_face );
1657  MB_CHK_ERR( error );
1658  }
1659 
1660  // error = ahf->print_tags(3);
1661 
1662  return MB_SUCCESS;
1663 }
1664 
1665 ErrorCode NestedRefine::subdivide_tets( int cur_level, int deg )
1666 {
1667  ErrorCode error;
1668  int nverts_prev, nents_prev;
1669  if( cur_level )
1670  {
1671  nverts_prev = level_mesh[cur_level - 1].num_verts;
1672  nents_prev = level_mesh[cur_level - 1].num_cells;
1673  }
1674  else
1675  {
1676  nverts_prev = _inverts.size();
1677  nents_prev = _incells.size();
1678  }
1679 
1680  EntityType type = MBTET;
1681  int cindex = type - 1;
1682  int d = get_index_from_degree( deg );
1683  int ne = refTemplates[cindex][d].nv_edge;
1684  int nvf = refTemplates[cindex][d].nv_face;
1685  int nvtotal = refTemplates[cindex][d].total_new_verts;
1686 
1687  int index = ahf->get_index_in_lmap( *( _incells.begin() ) );
1688  int nvpc = ahf->lConnMap3D[index].num_verts_in_cell;
1689  int nepc = ahf->lConnMap3D[index].num_edges_in_cell;
1690  int nfpc = ahf->lConnMap3D[index].num_faces_in_cell;
1691 
1692  // Create vertex buffer
1693  int vtotal = nvpc + nvtotal;
1694  std::vector< EntityHandle > vbuffer( vtotal );
1695 
1696  // Create book-keeping arrays over the parent mesh to avoid introducing duplicate vertices
1697  std::vector< EntityHandle > trackvertsC_edg( nepc * ne * nents_prev, 0 );
1698  std::vector< EntityHandle > trackvertsC_face( nfpc * nvf * nents_prev, 0 );
1699 
1700  int cur_nverts = level_mesh[cur_level].num_verts;
1701  std::vector< int > flag_verts( cur_nverts - nverts_prev, 0 );
1702  std::vector< int > cell_patterns( nents_prev, 0 );
1703 
1704  int count_nverts = nverts_prev;
1705  int count_ents = 0;
1706  std::vector< EntityHandle > conn, cur_conn;
1707 
1708  // Step 1: Create the subentities via refinement of the previous mesh
1709  for( int cid = 0; cid < nents_prev; cid++ )
1710  {
1711  conn.clear();
1712  cur_conn.clear();
1713  for( int i = 0; i < vtotal; i++ )
1714  vbuffer[i] = 0;
1715 
1716  // EntityHandle of the working cell
1717  EntityHandle cell;
1718  if( cur_level )
1719  cell = level_mesh[cur_level - 1].start_cell + cid;
1720  else
1721  cell = _incells[cid];
1722 
1723  error = get_connectivity( cell, cur_level, conn );
1724  MB_CHK_ERR( error );
1725 
1726  // Step 1: Add vertices from the current level for the working face that will be used for
1727  // subdivision.
1728  // Add the corners to vbuffer
1729  for( int i = 0; i < (int)conn.size(); i++ )
1730  {
1731  if( cur_level )
1732  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - level_mesh[cur_level - 1].start_vertex );
1733  else
1734  vbuffer[i] = level_mesh[cur_level].start_vertex + ( conn[i] - *_inverts.begin() );
1735 
1736  cur_conn.push_back( vbuffer[i] );
1737  }
1738 
1739  // Gather vertices already added to tracking array due to refinement of the sibling cells
1740  for( int i = 0; i < nepc; i++ )
1741  {
1742  for( int j = 0; j < ne; j++ )
1743  {
1744  int idx = refTemplates[cindex][d].vert_on_edges[i][j];
1745  vbuffer[idx] = trackvertsC_edg[cid * nepc * ne + ne * i + j];
1746  }
1747  }
1748 
1749  // Add remaining new vertex handles
1750  for( int i = 0; i < nfpc; i++ )
1751  {
1752  for( int j = 0; j < nvf; j++ )
1753  {
1754  int idx = refTemplates[cindex][d].vert_on_faces[i][j];
1755  vbuffer[idx] = trackvertsC_face[cid * nfpc * nvf + nvf * i + j];
1756  }
1757  }
1758 
1759  // Add the remaining vertex handles to vbuffer for the current level for the working cell
1760  for( int i = 0; i < nvtotal; i++ )
1761  {
1762  if( !vbuffer[i + nvpc] )
1763  {
1764  vbuffer[i + nvpc] = level_mesh[cur_level].start_vertex + count_nverts;
1765  count_nverts += 1;
1766  }
1767  }
1768 
1769  // Step 2: Coordinates of the new vertices
1770  std::vector< double > corner_coords( nvpc * 3 );
1771  error = get_coordinates( &cur_conn[0], nvpc, cur_level + 1, &corner_coords[0] );
1772  MB_CHK_ERR( error );
1773 
1774  error = compute_coordinates( cur_level, deg, type, &vbuffer[0], vtotal, &corner_coords[0], flag_verts,
1775  nverts_prev );
1776  MB_CHK_ERR( error );
1777 
1778  // Step 3: Choose the tet refine pattern to be used for this tet
1779  int diag = find_shortest_diagonal_octahedron( cur_level, deg, &vbuffer[0] );
1780  int pat_id = diag + 2;
1781  cell_patterns[cid] = pat_id;
1782 
1783  // Step 4: Use the template to obtain the subentities. The coordinates and local ahf maps
1784  // are also constructed. Connectivity of the children
1785  int etotal = refTemplates[pat_id][d].total_new_ents;
1786  std::vector< EntityHandle > ent_buffer( etotal );
1787 
1788  for( int i = 0; i < etotal; i++ )
1789  {
1790  for( int k = 0; k < nvpc; k++ )
1791  {
1792  int idx = refTemplates[pat_id][d].ents_conn[i][k];
1793  level_mesh[cur_level].cell_conn[nvpc * count_ents + k] = vbuffer[idx];
1794  }
1795  ent_buffer[i] = level_mesh[cur_level].start_cell + count_ents;
1796  count_ents += 1;
1797  }
1798 
1799  // Step 5: Update local ahf maps
1800  error = update_local_ahf( deg, MBTET, pat_id, &vbuffer[0], &ent_buffer[0], etotal );
1801  MB_CHK_ERR( error );
1802 
1803  // Step 6: Update tracking information
1804  error = update_tracking_verts( cell, cur_level, deg, trackvertsC_edg, trackvertsC_face, &vbuffer[0] );
1805  MB_CHK_ERR( error );
1806  }
1807 
1808  // Step 7: Update the global maps
1809  // error = update_global_ahf(cur_level, deg, cell_patterns); MB_CHK_ERR(error);
1810  error = update_global_ahf( type, cur_level, deg, &cell_patterns );
1811  MB_CHK_ERR( error );
1812 
1813  // Step 8: If edges exists, refine them as well.
1814  if( level_mesh[cur_level].num_edges != 0 )
1815  {
1816  error = construct_hm_1D( cur_level, deg, type, trackvertsC_edg );
1817  MB_CHK_ERR( error );
1818  }
1819 
1820  // Step 9: If faces exists, refine them as well.
1821  if( !_infaces.empty() )
1822  {
1823  error = construct_hm_2D( cur_level, deg, type, trackvertsC_edg, trackvertsC_face );
1824  MB_CHK_ERR( error );
1825  }
1826 
1827  return MB_SUCCESS;
1828 }
1829 
1831  int deg,
1832  EntityType type,
1833  EntityHandle* vbuffer,
1834  int vtotal,
1835  double* corner_coords,
1836  std::vector< int >& vflag,
1837  int nverts_prev )
1838 {
1839  EntityHandle vstart = level_mesh[cur_level].start_vertex;
1840  int d = get_index_from_degree( deg );
1841 
1842  if( type == MBTRI )
1843  {
1844  double xi, eta, N[3];
1845  int findex = mbImpl->type_from_handle( *( _infaces.begin() ) ) - 1;
1846 
1847  for( int i = 3; i < vtotal; i++ )
1848  {
1849  if( vflag[vbuffer[i] - vstart - nverts_prev] ) continue;
1850 
1851  xi = refTemplates[findex][d].vert_nat_coord[i - 3][0];
1852  eta = refTemplates[findex][d].vert_nat_coord[i - 3][1];
1853  N[0] = 1 - xi - eta;
1854  N[1] = xi;
1855  N[2] = eta;
1856 
1857  double x = 0, y = 0, z = 0;
1858  for( int j = 0; j < 3; j++ )
1859  {
1860  x += N[j] * corner_coords[3 * j];
1861  y += N[j] * corner_coords[3 * j + 1];
1862  z += N[j] * corner_coords[3 * j + 2];
1863  }
1864 
1865  level_mesh[cur_level].coordinates[0][vbuffer[i] - vstart] = x;
1866  level_mesh[cur_level].coordinates[1][vbuffer[i] - vstart] = y;
1867  level_mesh[cur_level].coordinates[2][vbuffer[i] - vstart] = z;
1868  vflag[vbuffer[i] - vstart - nverts_prev] = 1;
1869  }
1870  }
1871  else if( type == MBQUAD )
1872  {
1873  double xi, eta, N[4];
1874  int findex = mbImpl->type_from_handle( *( _infaces.begin() ) ) - 1;
1875 
1876  for( int i = 4; i < vtotal; i++ )
1877  {
1878  if( vflag[vbuffer[i] - vstart - nverts_prev] ) continue;
1879 
1880  xi = refTemplates[findex][d].vert_nat_coord[i - 4][0];
1881  eta = refTemplates[findex][d].vert_nat_coord[i - 4][1];
1882  N[0] = ( 1 - xi ) * ( 1 - eta ) / 4;
1883  N[1] = ( 1 + xi ) * ( 1 - eta ) / 4;
1884  N[2] = ( 1 + xi ) * ( 1 + eta ) / 4, N[3] = ( 1 - xi ) * ( 1 + eta ) / 4;
1885 
1886  double x = 0, y = 0, z = 0;
1887  for( int j = 0; j < 4; j++ )
1888  {
1889  x += N[j] * corner_coords[3 * j];
1890  y += N[j] * corner_coords[3 * j + 1];
1891  z += N[j] * corner_coords[3 * j + 2];
1892  }
1893 
1894  level_mesh[cur_level].coordinates[0][vbuffer[i] - vstart] = x;
1895  level_mesh[cur_level].coordinates[1][vbuffer[i] - vstart] = y;
1896  level_mesh[cur_level].coordinates[2][vbuffer[i] - vstart] = z;
1897  vflag[vbuffer[i] - vstart - nverts_prev] = 1;
1898  }
1899  }
1900  else if( type == MBTET )
1901  {
1902  double xi, eta, mu, N[4];
1903  int cindex = mbImpl->type_from_handle( *( _incells.begin() ) ) - 1;
1904 
1905  for( int i = 4; i < vtotal; i++ )
1906  {
1907  if( vflag[vbuffer[i] - vstart - nverts_prev] ) continue;
1908 
1909  xi = refTemplates[cindex][d].vert_nat_coord[i - 4][0];
1910  eta = refTemplates[cindex][d].vert_nat_coord[i - 4][1];
1911  mu = refTemplates[cindex][d].vert_nat_coord[i - 4][2];
1912 
1913  N[0] = 1 - xi - eta - mu;
1914  N[1] = xi;
1915  N[2] = eta, N[3] = mu;
1916 
1917  double x = 0, y = 0, z = 0;
1918  for( int j = 0; j < 4; j++ )
1919  {
1920  x += N[j] * corner_coords[3 * j];
1921  y += N[j] * corner_coords[3 * j + 1];
1922  z += N[j] * corner_coords[3 * j + 2];
1923  }
1924 
1925  level_mesh[cur_level].coordinates[0][vbuffer[i] - vstart] = x;
1926  level_mesh[cur_level].coordinates[1][vbuffer[i] - vstart] = y;
1927  level_mesh[cur_level].coordinates[2][vbuffer[i] - vstart] = z;
1928  vflag[vbuffer[i] - vstart - nverts_prev] = 1;
1929  }
1930  }
1931  else if( type == MBPRISM )
1932  {
1933  double xi, eta, mu, N[6];
1934  int cindex = mbImpl->type_from_handle( *( _incells.begin() ) ) - 1;
1935 
1936  for( int i = 6; i < vtotal; i++ )
1937  {
1938  if( vflag[vbuffer[i] - vstart - nverts_prev] ) continue;
1939 
1940  xi = refTemplates[cindex][d].vert_nat_coord[i - 6][0];
1941  eta = refTemplates[cindex][d].vert_nat_coord[i - 6][1];
1942  mu = refTemplates[cindex][d].vert_nat_coord[i - 6][2];
1943 
1944  N[0] = ( 1 - xi - eta ) * ( 1 - mu ), N[1] = xi * ( 1 - mu ), N[2] = eta * ( 1 - mu ),
1945  N[3] = ( 1 - xi - eta ) * ( 1 + mu ), N[4] = xi * ( 1 + mu ), N[5] = eta * ( 1 + mu );
1946 
1947  double x = 0, y = 0, z = 0;
1948  for( int j = 0; j < 6; j++ )
1949  {
1950  x += N[j] * corner_coords[3 * j];
1951  y += N[j] * corner_coords[3 * j + 1];
1952  z += N[j] * corner_coords[3 * j + 2];
1953  }
1954 
1955  level_mesh[cur_level].coordinates[0][vbuffer[i] - vstart] = x;
1956  level_mesh[cur_level].coordinates[1][vbuffer[i] - vstart] = y;
1957  level_mesh[cur_level].coordinates[2][vbuffer[i] - vstart] = z;
1958  vflag[vbuffer[i] - vstart - nverts_prev] = 1;
1959  }
1960  }
1961  else if( type == MBHEX )
1962  {
1963  double xi, eta, mu, N[8];
1964  double d1, d2, d3, s1, s2, s3;
1965  int cindex = mbImpl->type_from_handle( *( _incells.begin() ) ) - 1;
1966 
1967  for( int i = 8; i < vtotal; i++ )
1968  {
1969 
1970  if( vflag[vbuffer[i] - vstart - nverts_prev] ) continue;
1971 
1972  xi = refTemplates[cindex][d].vert_nat_coord[i - 8][0];
1973  eta = refTemplates[cindex][d].vert_nat_coord[i - 8][1];
1974  mu = refTemplates[cindex][d].vert_nat_coord[i - 8][2];
1975 
1976  d1 = 1 - xi;
1977  d2 = 1 - eta;
1978  d3 = 1 - mu;
1979  s1 = 1 + xi;
1980  s2 = 1 + eta;
1981  s3 = 1 + mu;
1982  N[0] = ( d1 * d2 * d3 ) / 8;
1983  N[1] = ( s1 * d2 * d3 ) / 8;
1984  N[2] = ( s1 * s2 * d3 ) / 8;
1985  N[3] = ( d1 * s2 * d3 ) / 8;
1986  N[4] = ( d1 * d2 * s3 ) / 8;
1987  N[5] = ( s1 * d2 * s3 ) / 8;
1988  N[6] = ( s1 * s2 * s3 ) / 8;
1989  N[7] = ( d1 * s2 * s3 ) / 8;
1990 
1991  double x = 0, y = 0, z = 0;
1992  for( int j = 0; j < 8; j++ )
1993  {
1994  x += N[j] * corner_coords[3 * j];
1995  y += N[j] * corner_coords[3 * j + 1];
1996  z += N[j] * corner_coords[3 * j + 2];
1997  }
1998 
1999  level_mesh[cur_level].coordinates[0][vbuffer[i] - vstart] = x;
2000  level_mesh[cur_level].coordinates[1][vbuffer[i] - vstart] = y;
2001  level_mesh[cur_level].coordinates[2][vbuffer[i] - vstart] = z;
2002 
2003  vflag[vbuffer[i] - vstart - nverts_prev] = 1;
2004  }
2005  }
2006  return MB_SUCCESS;
2007 }
2008 /**********************************
2009  * Parallel Communication *
2010  * ********************************/
2011 
2012 #ifdef MOAB_HAVE_MPI
2013 ErrorCode NestedRefine::resolve_shared_ents_parmerge( int level, EntityHandle levelset )
2014 {
2015  // TEMP: Add the adjacencies for MOAB-native DS
2016  // NOTE (VSM): This is expensive since it creates a doubly
2017  // redundant copy of the adjacency data in both MOAB-native
2018  // and AHF. Need to fix this with AHF optimized branch.
2019  ErrorCode error;
2020  ReadUtilIface* read_iface;
2021  error = mbImpl->query_interface( read_iface );
2022  MB_CHK_ERR( error );
2023  if( level_mesh[level].num_edges != 0 )
2024  {
2025  error = read_iface->update_adjacencies( level_mesh[level].start_edge, level_mesh[level].num_edges, 2,
2026  level_mesh[level].edge_conn );
2027  MB_CHK_ERR( error );
2028  }
2029  if( level_mesh[level].num_faces != 0 )
2030  {
2031  EntityType type = mbImpl->type_from_handle( *( _infaces.begin() ) );
2032  int nvpf = ahf->lConnMap2D[type - 2].num_verts_in_face;
2033  error = read_iface->update_adjacencies( level_mesh[level].start_face, level_mesh[level].num_faces, nvpf,
2034  level_mesh[level].face_conn );
2035  MB_CHK_ERR( error );
2036  }
2037  if( level_mesh[level].num_cells != 0 )
2038  {
2039  int index = ahf->get_index_in_lmap( *_incells.begin() );
2040  int nvpc = ahf->lConnMap3D[index].num_verts_in_cell;
2041  error = read_iface->update_adjacencies( level_mesh[level].start_cell, level_mesh[level].num_cells, nvpc,
2042  level_mesh[level].cell_conn );
2043  MB_CHK_ERR( error );
2044  }
2045 
2046  if( pcomm->size() > 1 )
2047  {
2048 
2049  // get all entities on the rootset
2050  moab::Range vtxs, edgs, facs, elms;
2051  error = mbImpl->get_entities_by_dimension( levelset, 0, vtxs, false );
2052  MB_CHK_ERR( error );
2053  error = mbImpl->get_entities_by_dimension( levelset, 1, edgs, false );
2054  MB_CHK_ERR( error );
2055  error = mbImpl->get_entities_by_dimension( levelset, 2, facs, false );
2056  MB_CHK_ERR( error );
2057  error = mbImpl->get_entities_by_dimension( levelset, 3, elms, false );
2058  MB_CHK_ERR( error );
2059 
2060  // set the parallel partition tag data
2061  moab::Tag part_tag;
2062  int partid = pcomm->rank(), dum_id = -1;
2063  error = mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, moab::MB_TYPE_INTEGER, part_tag,
2065  MB_CHK_ERR( error );
2066  error = mbImpl->tag_set_data( part_tag, &levelset, 1, &partid );
2067  MB_CHK_ERR( error );
2068  //
2069  // Now that we have the local piece of the mesh refined consistently,
2070  // call parallel merge instead of resolved_shared to stitch together the meshes
2071  // and to handle parallel communication of remote proc/entity-handle pairs for
2072  // shared + non-owned interfaces entities.
2073  //
2074  // TODO: This needs to be replaced by the following scheme in the future as
2075  // an optimization step.
2076  // > Assign global IDs consistently for shared entities so that parallel
2077  // > resolve shared ents can happen out of the box. This is the fastest option.
2078 
2079  ParallelMergeMesh pm( pcomm, 1e-08 );
2080  error = pm.merge( levelset, true );
2081  MB_CHK_ERR( error );
2082 
2083  //
2084  // Parallel Communication complete - all entities resolved
2085  //
2086  }
2087  return MB_SUCCESS;
2088 }
2089 
2090 ErrorCode NestedRefine::resolve_shared_ents_opt( EntityHandle* hm_set, int num_levels )
2091 {
2092  assert( pcomm->size() > 1 );
2093 
2094  ErrorCode error;
2095 
2096  // Step 1A: Pre-processing: setting the parallel partition tag data
2097  for( int i = 0; i < num_levels; i++ )
2098  {
2099  Tag part_tag;
2100  int partid = pcomm->rank(), dum_id = -1;
2101  error = mbImpl->tag_get_handle( "PARALLEL_PARTITION", 1, moab::MB_TYPE_INTEGER, part_tag,
2103  MB_CHK_ERR( error );
2104  error = mbImpl->tag_set_data( part_tag, &hm_set[i], 1, &partid );
2105  MB_CHK_ERR( error );
2106  }
2107 
2108  // Step 1B: Pre-processing: gather all shared entities and list entities shared with each
2109  // sharing processor
2110 
2111  // All shared processors
2112  std::set< unsigned int > shprocs;
2113  error = pcomm->get_comm_procs( shprocs );
2114  MB_CHK_ERR( error );
2115 
2116  std::vector< int > sharedprocs;
2117  for( std::set< unsigned int >::iterator it = shprocs.begin(); it != shprocs.end(); it++ )
2118  sharedprocs.push_back( *it );
2119  int nprocs = sharedprocs.size();
2120 
2121  // Create buffer variables storing the entities to be sent and received
2122  std::vector< std::vector< int > > nsharedEntsperproc( nprocs );
2123  std::vector< std::vector< EntityHandle > > localBuffs( nprocs );
2124  std::vector< std::vector< EntityHandle > > remlocalBuffs( nprocs );
2125  std::vector< std::vector< EntityHandle > > remoteBuffs( nprocs );
2126 
2127  int i;
2128  Range sharedentities;
2129 
2130  for( i = 0; i < nprocs; i++ )
2131  {
2132  // List of shared entities at the coarsest level
2133  sharedentities.clear();
2134  error = pcomm->get_shared_entities( sharedprocs[i], sharedentities, -1, true );
2135  MB_CHK_ERR( error );
2136 
2137  // Get the list shared edges and vertices that are not part of the shared edges
2138  Range allEnts;
2139  error = collect_shared_entities_by_dimension( sharedentities, allEnts );
2140  MB_CHK_ERR( error );
2141 
2142  Range V0, E0, F0;
2143  V0 = allEnts.subset_by_dimension( 0 );
2144  E0 = allEnts.subset_by_dimension( 1 );
2145  F0 = allEnts.subset_by_dimension( 2 );
2146 
2147  // Step 2A: Prepare msg to be sent:
2148  //
2149  // FList = <F, FC, FE> where F, FC and FE are vectors containing the faces, their
2150  // connectivities and edges. F = <F_0, F_1, F_2, ..., F_L> where
2151  // F_0 is the list of shared faces at the coarsest level,
2152  // F_i are the list of children faces at subsequent levels.
2153  // FC vector contains the connectivities of F_i's and FE vector contains the bounding edges
2154  // of F_i's.
2155  //
2156  // EList = <E, EC> where E and EC are vectors containing the edges and their connectivities.
2157  // E = <E_0, E_1, ..., E_L> where
2158  // E_0 is the list of shared edges at the coarsest level and
2159  // E_i are the list of children edges at subsequent levels.
2160  // The EC vector contains the connectivities of E_i's.
2161  //
2162  // VList = <V> = <V_0, V_1, ...., V_L> where V_0 are shared vertices at the coarsest level
2163  // and V_i are the duplicates in the subsequent levels.
2164 
2165  std::vector< EntityHandle > locFList, remFList;
2166  std::vector< EntityHandle > locEList, remEList;
2167  std::vector< EntityHandle > locVList, remVList;
2168 
2169  // collect faces
2170  if( !F0.empty() )
2171  {
2172  error = collect_FList( sharedprocs[i], F0, locFList, remFList );
2173  MB_CHK_ERR( error );
2174  }
2175 
2176  // collect edges
2177  if( !E0.empty() )
2178  {
2179  error = collect_EList( sharedprocs[i], E0, locEList, remEList );
2180  MB_CHK_ERR( error );
2181  }
2182 
2183  // collect vertices
2184  if( !V0.empty() )
2185  {
2186  error = collect_VList( sharedprocs[i], V0, locVList, remVList );
2187  MB_CHK_ERR( error );
2188  }
2189 
2190  // Step 2B: Add data to NR local buffer to be sent
2191  std::vector< int > msgsz;
2192  msgsz.push_back( F0.size() );
2193  msgsz.push_back( locFList.size() );
2194  msgsz.push_back( E0.size() );
2195  msgsz.push_back( locEList.size() );
2196  msgsz.push_back( V0.size() );
2197  msgsz.push_back( locVList.size() );
2198  nsharedEntsperproc[i].insert( nsharedEntsperproc[i].end(), msgsz.begin(), msgsz.end() );
2199 
2200  if( !F0.empty() )
2201  {
2202  localBuffs[i].insert( localBuffs[i].end(), locFList.begin(), locFList.end() );
2203  remlocalBuffs[i].insert( remlocalBuffs[i].end(), remFList.begin(), remFList.end() );
2204  }
2205  if( !E0.empty() )
2206  {
2207  localBuffs[i].insert( localBuffs[i].end(), locEList.begin(), locEList.end() );
2208  remlocalBuffs[i].insert( remlocalBuffs[i].end(), remEList.begin(), remEList.end() );
2209  }
2210  if( !V0.empty() )
2211  {
2212  localBuffs[i].insert( localBuffs[i].end(), locVList.begin(), locVList.end() );
2213  remlocalBuffs[i].insert( remlocalBuffs[i].end(), remVList.begin(), remVList.end() );
2214  }
2215  }
2216 
2217  // Step 3: Send and receive the remote collection of child ents
2218  error = pcomm->send_recv_entities( sharedprocs, nsharedEntsperproc, remlocalBuffs, remoteBuffs );
2219  MB_CHK_ERR( error );
2220 
2221  // Step 5: Resolve shared child entities and update parallel tags
2222  std::multimap< EntityHandle, int > rprocs;
2223  std::multimap< EntityHandle, EntityHandle > rhandles;
2224 
2225  error = decipher_remote_handles( sharedprocs, nsharedEntsperproc, localBuffs, remoteBuffs, rprocs, rhandles );
2226  MB_CHK_ERR( error );
2227 
2228  // Step 6: Update pcomm tags
2229  error = update_parallel_tags( rprocs, rhandles );
2230  MB_CHK_ERR( error );
2231 
2232  return MB_SUCCESS;
2233 }
2234 
2235 ErrorCode NestedRefine::collect_shared_entities_by_dimension( Range sharedEnts, Range& allEnts )
2236 {
2237  ErrorCode error;
2238 
2239  Range F0, E0, V0, E0all, V0all;
2240  std::vector< EntityHandle > ents;
2241 
2242  F0 = sharedEnts.subset_by_dimension( 2 );
2243  E0all = sharedEnts.subset_by_dimension( 1 );
2244  V0all = sharedEnts.subset_by_dimension( 0 );
2245 
2246  if( !F0.empty() )
2247  {
2248  Range edges, verts;
2249 
2250  for( Range::iterator it = F0.begin(); it != F0.end(); it++ )
2251  {
2252  ents.clear();
2253  error = ahf->get_adjacencies( *it, 1, ents );
2254  MB_CHK_ERR( error );
2255  std::copy( ents.begin(), ents.end(), range_inserter( edges ) );
2256  ents.clear();
2257  error = mbImpl->get_connectivity( &( *it ), 0, ents );
2258  MB_CHK_ERR( error );
2259  std::copy( ents.begin(), ents.end(), range_inserter( verts ) );
2260  }
2261 
2262  E0 = subtract( E0all, edges );
2263  if( !E0.empty() )
2264  {
2265  for( Range::iterator it = E0.begin(); it != E0.end(); it++ )
2266  {
2267  ents.clear();
2268  error = mbImpl->get_connectivity( &( *it ), 0, ents );
2269  MB_CHK_ERR( error );
2270  std::copy( ents.begin(), ents.end(), range_inserter( verts ) );
2271  }
2272  }
2273  V0 = subtract( V0all, verts );
2274  }
2275  else if( !E0all.empty() )
2276  {
2277  Range verts;
2278  for( Range::iterator it = E0all.begin(); it != E0all.end(); it++ )
2279  {
2280  ents.clear();
2281  error = mbImpl->get_connectivity( &( *it ), 1, ents );
2282  MB_CHK_ERR( error );
2283  std::copy( ents.begin(), ents.end(), range_inserter( verts ) );
2284  }
2285  E0 = E0all;
2286  V0 = subtract( V0all, verts );
2287  }
2288  else if( !V0all.empty() )
2289  {
2290  V0 = V0all;
2291  }
2292  else
2293  MB_SET_ERR( MB_FAILURE, "Trying to pack unsupported sub-entities for shared interface entities" );
2294 
2295  if( !F0.empty() ) std::copy( F0.begin(), F0.end(), range_inserter( allEnts ) );
2296  if( !E0.empty() ) std::copy( E0.begin(), E0.end(), range_inserter( allEnts ) );
2297  if( !V0.empty() ) std::copy( V0.begin(), V0.end(), range_inserter( allEnts ) );
2298 
2299  return MB_SUCCESS;
2300 }
2301 
2302 ErrorCode NestedRefine::collect_FList( int to_proc,
2303  Range faces,
2304  std::vector< EntityHandle >& FList,
2305  std::vector< EntityHandle >& RList )
2306 {
2307  ErrorCode error;
2308 
2309  FList.clear();
2310  std::vector< EntityHandle > F, FC, FE, lF, lFC, lFE, rF, rFC, rFE;
2311  std::vector< EntityHandle > childEnts, conn, fedges;
2312 
2313  for( Range::iterator it = faces.begin(); it != faces.end(); it++ )
2314  {
2315  EntityHandle face = *it;
2316  conn.clear();
2317  fedges.clear();
2318  error = mbImpl->get_connectivity( &face, 1, conn );
2319  MB_CHK_ERR( error );
2320  error = ahf->get_face_edges( *it, fedges );
2321  MB_CHK_ERR( error );
2322 
2323  // add local handles
2324  lF.push_back( *it );
2325  lFC.insert( lFC.end(), conn.begin(), conn.end() );
2326  lFE.insert( lFE.end(), fedges.begin(), fedges.end() );
2327 
2328  // replace local handles with remote handles on to_proc
2329  EntityHandle rval = 0;
2330  error = pcomm->get_remote_handles( &face, &rval, 1, to_proc );
2331  MB_CHK_ERR( error );
2332  rF.push_back( rval );
2333 
2334  for( int i = 0; i < (int)conn.size(); i++ )
2335  {
2336  error = pcomm->get_remote_handles( &conn[i], &rval, 1, to_proc );
2337  MB_CHK_ERR( error );
2338  rFC.push_back( rval );
2339 
2340  error = pcomm->get_remote_handles( &fedges[i], &rval, 1, to_proc );
2341  MB_CHK_ERR( error );
2342  rFE.push_back( rval );
2343  }
2344  }
2345 
2346  for( int l = 0; l < nlevels; l++ )
2347  {
2348  for( Range::iterator it = faces.begin(); it != faces.end(); it++ )
2349  {
2350  childEnts.clear();
2351  error = parent_to_child( *it, 0, l + 1, childEnts );
2352  MB_CHK_ERR( error );
2353 
2354  for( int i = 0; i < (int)childEnts.size(); i++ )
2355  {
2356  conn.clear();
2357  fedges.clear();
2358  error = mbImpl->get_connectivity( &childEnts[i], 1, conn );
2359  MB_CHK_ERR( error );
2360  error = ahf->get_face_edges( childEnts[i], fedges );
2361  MB_CHK_ERR( error );
2362 
2363  F.push_back( childEnts[i] );
2364  FC.insert( FC.end(), conn.begin(), conn.end() );
2365  FE.insert( FE.end(), fedges.begin(), fedges.end() );
2366  }
2367  }
2368  }
2369 
2370  FList.insert( FList.end(), lF.begin(), lF.end() );
2371  FList.insert( FList.end(), F.begin(), F.end() );
2372  FList.insert( FList.end(), lFC.begin(), lFC.end() );
2373  FList.insert( FList.end(), FC.begin(), FC.end() );
2374  FList.insert( FList.end(), lFE.begin(), lFE.end() );
2375  FList.insert( FList.end(), FE.begin(), FE.end() );
2376 
2377  RList.insert( RList.end(), rF.begin(), rF.end() );
2378  RList.insert( RList.end(), F.begin(), F.end() );
2379  RList.insert( RList.end(), rFC.begin(), rFC.end() );
2380  RList.insert( RList.end(), FC.begin(), FC.end() );
2381  RList.insert( RList.end(), rFE.begin(), rFE.end() );
2382  RList.insert( RList.end(), FE.begin(), FE.end() );
2383 
2384  return MB_SUCCESS;
2385 }
2386 
2387 ErrorCode NestedRefine::collect_EList( int to_proc,
2388  Range edges,
2389  std::vector< EntityHandle >& EList,
2390  std::vector< EntityHandle >& RList )
2391 {
2392  ErrorCode error;
2393  EList.clear();
2394  std::vector< EntityHandle > E, EC, lE, lEC, rE, rEC;
2395  std::vector< EntityHandle > childEnts, conn;
2396 
2397  // Add the edges and their connectivities at the coarsest level first.
2398  for( Range::iterator it = edges.begin(); it != edges.end(); it++ )
2399  {
2400  EntityHandle edg = *it;
2401  conn.clear();
2402  error = mbImpl->get_connectivity( &edg, 1, conn );
2403  MB_CHK_ERR( error );
2404 
2405  // add local handles
2406  lE.push_back( edg );
2407  lEC.insert( lEC.end(), conn.begin(), conn.end() );
2408 
2409  // replace local handles with remote handle on to_proc
2410  EntityHandle rval = 0;
2411  error = pcomm->get_remote_handles( &edg, &rval, 1, to_proc );
2412  MB_CHK_ERR( error );
2413  rE.push_back( rval );
2414  error = pcomm->get_remote_handles( &conn[0], &rval, 1, to_proc );
2415  MB_CHK_ERR( error );
2416  rEC.push_back( rval );
2417  error = pcomm->get_remote_handles( &conn[1], &rval, 1, to_proc );
2418  MB_CHK_ERR( error );
2419  rEC.push_back( rval );
2420  }
2421 
2422  // Add the edges and their connectivities at subsequent levels.
2423  for( int l = 0; l < nlevels; l++ )
2424  {
2425  for( Range::iterator it = edges.begin(); it != edges.end(); it++ )
2426  {
2427  childEnts.clear();
2428  error = parent_to_child( *it, 0, l + 1, childEnts );
2429  MB_CHK_ERR( error );
2430 
2431  for( int i = 0; i < (int)childEnts.size(); i++ )
2432  {
2433  conn.clear();
2434  error = mbImpl->get_connectivity( &childEnts[i], 1, conn );
2435  MB_CHK_ERR( error );
2436  E.push_back( childEnts[i] );
2437  EC.insert( EC.end(), conn.begin(), conn.end() );
2438  }
2439  }
2440  }
2441 
2442  EList.insert( EList.end(), lE.begin(), lE.end() );
2443  EList.insert( EList.end(), E.begin(), E.end() );
2444  EList.insert( EList.end(), lEC.begin(), lEC.end() );
2445  EList.insert( EList.end(), EC.begin(), EC.end() );
2446 
2447  RList.insert( RList.end(), rE.begin(), rE.end() );
2448  RList.insert( RList.end(), E.begin(), E.end() );
2449  RList.insert( RList.end(), rEC.begin(), rEC.end() );
2450  RList.insert( RList.end(), EC.begin(), EC.end() );
2451 
2452  return MB_SUCCESS;
2453 }
2454 
2455 ErrorCode NestedRefine::collect_VList( int to_proc,
2456  Range verts,
2457  std::vector< EntityHandle >& VList,
2458  std::vector< EntityHandle >& RList )
2459 {
2460  ErrorCode error;
2461  std::vector< EntityHandle > V, lV, rV;
2462  VList.clear();
2463 
2464  // Add the vertices at the coarsest level first.
2465  for( Range::iterator it = verts.begin(); it != verts.end(); it++ )
2466  {
2467  EntityHandle v = *it;
2468 
2469  lV.push_back( v );
2470  EntityHandle rval = 0;
2471  error = pcomm->get_remote_handles( &v, &rval, 1, to_proc );
2472  MB_CHK_ERR( error );
2473 
2474  rV.push_back( rval );
2475  }
2476 
2477  // Add the vertices at the subsequent levels .
2478  for( int l = 0; l < nlevels; l++ )
2479  {
2480  for( Range::iterator it = verts.begin(); it != verts.end(); it++ )
2481  {
2482  EntityHandle dupvert = 0;
2483  error = get_vertex_duplicates( *it, l + 1, dupvert );
2484  MB_CHK_ERR( error );
2485  V.push_back( dupvert );
2486  }
2487  }
2488 
2489  // local vertex handles at the coarsest level
2490  VList.insert( VList.end(), lV.begin(), lV.end() );
2491  VList.insert( VList.end(), V.begin(), V.end() );
2492 
2493  // remote vertex handles at the coarsest level
2494  RList.insert( RList.end(), rV.begin(), rV.end() );
2495  RList.insert( RList.end(), V.begin(), V.end() );
2496 
2497  return MB_SUCCESS;
2498 }
2499 
2500 ErrorCode NestedRefine::decipher_remote_handles( std::vector< int >& sharedprocs,
2501  std::vector< std::vector< int > >& auxinfo,
2502  std::vector< std::vector< EntityHandle > >& localbuffers,
2503  std::vector< std::vector< EntityHandle > >& remotebuffers,
2504  std::multimap< EntityHandle, int >& remProcs,
2505  std::multimap< EntityHandle, EntityHandle >& remHandles )
2506 {
2507  ErrorCode error;
2508 
2509  int i;
2510  int nprocs = sharedprocs.size();
2511 
2512  for( i = 0; i < nprocs; i++ )
2513  {
2514  std::vector< int > msgsz;
2515  for( int j = 0; j < (int)auxinfo[i].size(); j++ )
2516  {
2517  msgsz.push_back( auxinfo[i][j] );
2518  }
2519 
2520  if( msgsz[0] != 0 ) // Faces
2521  {
2522  // Get the local and remote face handles from the buffers
2523  std::vector< EntityHandle > LFList, RFList;
2524  LFList.insert( LFList.end(), localbuffers[i].begin(), localbuffers[i].begin() + msgsz[1] );
2525  RFList.insert( RFList.end(), remotebuffers[i].begin(), remotebuffers[i].begin() + msgsz[1] );
2526 
2527  error = decipher_remote_handles_face( sharedprocs[i], msgsz[0], LFList, RFList, remProcs, remHandles );
2528  MB_CHK_ERR( error );
2529 
2530  if( msgsz[2] != 0 ) // Edges
2531  {
2532  std::vector< EntityHandle > LEList, REList;
2533  LEList.insert( LEList.end(), localbuffers[i].begin() + msgsz[1] + 1,
2534  localbuffers[i].begin() + msgsz[1] + msgsz[3] );
2535  REList.insert( REList.end(), remotebuffers[i].begin() + msgsz[1] + 1,
2536  remotebuffers[i].begin() + msgsz[1] + msgsz[3] );
2537 
2538  error = decipher_remote_handles_edge( sharedprocs[i], msgsz[2], LEList, REList, remProcs, remHandles );
2539  MB_CHK_ERR( error );
2540 
2541  if( msgsz[4] != 0 ) // Vertices
2542  {
2543  // Get the local and remote face handles from the buffers
2544  std::vector< EntityHandle > LVList, RVList;
2545  LVList.insert( LVList.end(), localbuffers[i].begin() + msgsz[1] + msgsz[3] + 1,
2546  localbuffers[i].begin() + msgsz[1] + msgsz[3] + msgsz[5] );
2547  RVList.insert( RVList.end(), remotebuffers[i].begin() + msgsz[1] + msgsz[3] + 1,
2548  remotebuffers[i].begin() + msgsz[1] + msgsz[3] + msgsz[5] );
2549 
2550  error = decipher_remote_handles_vertex( sharedprocs[i], msgsz[4], LVList, RVList, remProcs,
2551  remHandles );
2552  MB_CHK_ERR( error );
2553  }
2554  }
2555  else if( msgsz[4] != 0 ) // Vertices
2556  {
2557  // Get the local and remote face handles from the buffers
2558  std::vector< EntityHandle > LVList, RVList;
2559  LVList.insert( LVList.end(), localbuffers[i].begin() + msgsz[1] + 1,
2560  localbuffers[i].begin() + msgsz[1] + msgsz[5] );
2561  RVList.insert( RVList.end(), remotebuffers[i].begin() + msgsz[1] + 1,
2562  remotebuffers[i].begin() + msgsz[1] + msgsz[5] );
2563 
2564  error =
2565  decipher_remote_handles_vertex( sharedprocs[i], msgsz[4], LVList, RVList, remProcs, remHandles );
2566  MB_CHK_ERR( error );
2567  }
2568  }
2569 
2570  else if( msgsz[2] != 0 ) // Edges
2571  {
2572  // Get the local and remote face handles from the buffers
2573  std::vector< EntityHandle > LEList, REList;
2574  LEList.insert( LEList.end(), localbuffers[i].begin(), localbuffers[i].begin() + msgsz[3] );
2575  REList.insert( REList.end(), remotebuffers[i].begin(), remotebuffers[i].begin() + msgsz[3] );
2576 
2577  error = decipher_remote_handles_edge( sharedprocs[i], msgsz[2], LEList, REList, remProcs, remHandles );
2578  MB_CHK_ERR( error );
2579 
2580  if( msgsz[4] != 0 ) // Vertices
2581  {
2582  // Get the local and remote face handles from the buffers
2583  std::vector< EntityHandle > LVList, RVList;
2584  LVList.insert( LVList.end(), localbuffers[i].begin() + msgsz[3] + 1,
2585  localbuffers[i].begin() + msgsz[3] + msgsz[5] );
2586  RVList.insert( RVList.end(), remotebuffers[i].begin() + msgsz[3] + 1,
2587  remotebuffers[i].begin() + msgsz[3] + msgsz[5] );
2588 
2589  error =
2590  decipher_remote_handles_vertex( sharedprocs[i], msgsz[4], LVList, RVList, remProcs, remHandles );
2591  MB_CHK_ERR( error );
2592  }
2593  }
2594 
2595  else if( msgsz[4] != 0 ) // Vertices
2596  {
2597  // Get the local and remote face handles from the buffers
2598  std::vector< EntityHandle > LVList, RVList;
2599  LVList.insert( LVList.end(), localbuffers[i].begin(), localbuffers[i].end() );
2600  RVList.insert( RVList.end(), remotebuffers[i].begin(), remotebuffers[i].end() );
2601 
2602  error = decipher_remote_handles_vertex( sharedprocs[i], msgsz[4], LVList, RVList, remProcs, remHandles );
2603  MB_CHK_ERR( error );
2604  }
2605  else
2606  MB_SET_ERR( MB_FAILURE, "Trying to decipher entities other than verts, edges, faces" );
2607  }
2608 
2609  return MB_SUCCESS;
2610 }
2611 
2612 ErrorCode NestedRefine::decipher_remote_handles_face( int shared_proc,
2613  int numfaces,
2614  std::vector< EntityHandle >& localFaceList,
2615  std::vector< EntityHandle >& remFaceList,
2616  std::multimap< EntityHandle, int >& remProcs,
2617  std::multimap< EntityHandle, EntityHandle >& remHandles )
2618 {
2619  ErrorCode error;
2620 
2621  for( int i = 0; i < numfaces; i++ )
2622  {
2623  // find local and remote handles of the coarsest face
2624  EntityHandle Lface = localFaceList[i];
2625  int Rface_idx =
2626  ( std::find( remFaceList.begin(), remFaceList.begin() + numfaces - 1, Lface ) ) - remFaceList.begin();
2627 
2628  // get connectivities of the local and remote coarsest faces
2629  std::vector< EntityHandle > Lface_conn, Rface_conn;
2630  error = get_data_from_buff( 2, 1, 0, i, numfaces, localFaceList, Lface_conn );
2631  MB_CHK_ERR( error );
2632  error = get_data_from_buff( 2, 1, 0, Rface_idx, numfaces, remFaceList, Rface_conn );
2633  MB_CHK_ERR( error );
2634 
2635  // find the combination difference between local and remote coarsest face
2636  std::vector< int > cmap;
2637  int comb = 0;
2638  int nvF = (int)Lface_conn.size();
2639  error = reorder_indices( &Lface_conn[0], &Rface_conn[0], nvF, &cmap[0], comb );
2640  MB_CHK_ERR( error );
2641 
2642  // go into loop over all levels
2643  std::vector< EntityHandle > lchildents, lparents;
2644  std::vector< EntityHandle > lcents, rcents;
2645  int lidx, ridx;
2646 
2647  for( int l = 0; l < nlevels; l++ )
2648  {
2649  lchildents.clear();
2650  lparents.clear();
2651  lcents.clear();
2652  rcents.clear();
2653 
2654  // obtain children at the current level
2655  error = get_data_from_buff( 2, 0, l + 1, i, numfaces, localFaceList, lchildents );
2656  MB_CHK_ERR( error );
2657 
2658  // obtain parents at the previous level
2659  if( l == 0 )
2660  {
2661  lparents.push_back( Lface );
2662  }
2663  else
2664  {
2665  error = get_data_from_buff( 2, 0, l, i, numfaces, localFaceList, lparents );
2666  MB_CHK_ERR( error );
2667  }
2668 
2669  //#children at the previous level and the current level
2670  EntityType ftype = mbImpl->type_from_handle( Lface );
2671  int d = get_index_from_degree( level_dsequence[l] );
2672  int nch = refTemplates[ftype - 1][d].total_new_ents;
2673  std::vector< int > fmap;
2674  error = reorder_indices( level_dsequence[l], nvF, comb, &fmap[0] );
2675  MB_CHK_ERR( error );
2676 
2677  // loop over all the lparents
2678  for( int j = 0; j < (int)lparents.size(); j++ )
2679  {
2680  // list local childrent at the current level
2681  lidx = std::find( localFaceList.begin(), localFaceList.end(), lparents[j] ) - localFaceList.begin();
2682  error = get_data_from_buff( 2, 0, l + 1, lidx, numfaces, localFaceList, lcents );
2683  MB_CHK_ERR( error );
2684 
2685  // find the corresponding remote of lparent and its children
2686  EntityHandle rparent = 0;
2687  error = check_for_parallelinfo( lparents[j], shared_proc, remHandles, remProcs, rparent );
2688  MB_CHK_ERR( error );
2689  ridx = std::find( remFaceList.begin(), remFaceList.end(), rparent ) - remFaceList.begin();
2690  error = get_data_from_buff( 2, 0, l + 1, ridx, numfaces, remFaceList, rcents );
2691  MB_CHK_ERR( error );
2692 
2693  // match up local face with remote handles according to cmap
2694  std::vector< EntityHandle > lconn, rconn, ledg, redg;
2695  for( int k = 0; k < nch; k++ )
2696  {
2697  lconn.clear();
2698  rconn.clear();
2699  ledg.clear();
2700  redg.clear();
2701 
2702  // matching the local children face handles with their remotes
2703  bool found = check_for_parallelinfo( lcents[k], shared_proc, remProcs );
2704  if( !found )
2705  {
2706  remProcs.insert( std::pair< EntityHandle, int >( lcents[k], shared_proc ) );
2707  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lcents[k], rcents[fmap[k]] ) );
2708  }
2709 
2710  // find indices of the matched child face
2711  lidx = std::find( localFaceList.begin(), localFaceList.end(), lcents[k] ) - localFaceList.begin();
2712  ridx = std::find( remFaceList.begin(), remFaceList.end(), rcents[fmap[k]] ) - remFaceList.begin();
2713 
2714  // find bounding edges and connectivity of the matched child face
2715  error = get_data_from_buff( 2, 2, l + 1, lidx, numfaces, localFaceList, ledg );
2716  MB_CHK_ERR( error );
2717  error = get_data_from_buff( 2, 1, l + 1, lidx, numfaces, localFaceList, lconn );
2718  MB_CHK_ERR( error );
2719  error = get_data_from_buff( 2, 2, l + 1, ridx, numfaces, remFaceList, redg );
2720  MB_CHK_ERR( error );
2721  error = get_data_from_buff( 2, 1, l + 1, ridx, numfaces, remFaceList, rconn );
2722  MB_CHK_ERR( error );
2723 
2724  // now match the handles of the bounding edges and the vertices using
2725  // combination difference
2726  for( int m = 0; m < (int)ledg.size(); m++ )
2727  {
2728  found = check_for_parallelinfo( ledg[m], shared_proc, remProcs );
2729 
2730  if( !found )
2731  {
2732  remProcs.insert( std::pair< EntityHandle, int >( ledg[m], shared_proc ) );
2733  remHandles.insert( std::pair< EntityHandle, EntityHandle >( ledg[m], redg[cmap[m]] ) );
2734  }
2735 
2736  found = check_for_parallelinfo( lconn[m], shared_proc, remProcs );
2737 
2738  if( !found )
2739  {
2740  remProcs.insert( std::pair< EntityHandle, int >( lconn[m], shared_proc ) );
2741  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lconn[m], rconn[cmap[m]] ) );
2742  }
2743  }
2744  }
2745  }
2746  }
2747  }
2748 
2749  return MB_SUCCESS;
2750 }
2751 
2752 ErrorCode NestedRefine::decipher_remote_handles_edge( int shared_proc,
2753  int numedges,
2754  std::vector< EntityHandle >& localEdgeList,
2755  std::vector< EntityHandle >& remEdgeList,
2756  std::multimap< EntityHandle, int >& remProcs,
2757  std::multimap< EntityHandle, EntityHandle >& remHandles )
2758 {
2759  ErrorCode error;
2760 
2761  for( int i = 0; i < numedges; i++ )
2762  {
2763  EntityHandle Ledge = localEdgeList[i];
2764  int Redge_idx =
2765  ( std::find( remEdgeList.begin(), remEdgeList.begin() + numedges - 1, Ledge ) ) - remEdgeList.begin();
2766 
2767  std::vector< EntityHandle > Ledge_conn, Redge_conn;
2768  error = get_data_from_buff( 1, 1, 0, i, numedges, localEdgeList, Ledge_conn );
2769  MB_CHK_ERR( error );
2770  error = get_data_from_buff( 1, 1, 0, Redge_idx, numedges, remEdgeList, Redge_conn );
2771  MB_CHK_ERR( error );
2772 
2773  bool orient = true;
2774  if( ( Ledge_conn[0] == Redge_conn[1] ) && ( Ledge_conn[1] == Redge_conn[0] ) ) orient = false;
2775 
2776  if( orient ) assert( ( Ledge_conn[0] == Redge_conn[0] ) && ( Ledge_conn[1] == Redge_conn[1] ) );
2777 
2778  std::vector< EntityHandle > lchildEdgs, rchildEdgs, lconn, rconn;
2779  for( int l = 0; l < nlevels; l++ )
2780  {
2781  lchildEdgs.clear();
2782  rchildEdgs.clear();
2783  error = get_data_from_buff( 1, 0, l + 1, i, numedges, localEdgeList, lchildEdgs );
2784  MB_CHK_ERR( error );
2785  error = get_data_from_buff( 1, 0, l + 1, Redge_idx, numedges, remEdgeList, rchildEdgs );
2786  MB_CHK_ERR( error );
2787 
2788  int nchd = lchildEdgs.size();
2789  if( orient )
2790  {
2791  for( int j = 0; j < nchd; j++ )
2792  {
2793  // match entityhandles of child edges
2794  bool found = check_for_parallelinfo( lchildEdgs[j], shared_proc, remProcs );
2795  if( !found )
2796  {
2797  remProcs.insert( std::pair< EntityHandle, int >( lchildEdgs[j], shared_proc ) );
2798  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lchildEdgs[j], rchildEdgs[j] ) );
2799  }
2800 
2801  // match entityhandles of child vertices
2802  lconn.clear();
2803  rconn.clear();
2804 
2805  int lidx =
2806  std::find( localEdgeList.begin(), localEdgeList.end(), lchildEdgs[j] ) - localEdgeList.begin();
2807  int ridx = std::find( remEdgeList.begin(), remEdgeList.end(), rchildEdgs[j] ) - remEdgeList.begin();
2808 
2809  error = get_data_from_buff( 1, 1, l + 1, lidx, numedges, localEdgeList, lconn );
2810  MB_CHK_ERR( error );
2811  error = get_data_from_buff( 1, 1, l + 1, ridx, numedges, remEdgeList, rconn );
2812  MB_CHK_ERR( error );
2813 
2814  found = check_for_parallelinfo( lconn[0], shared_proc, remProcs );
2815  if( !found )
2816  {
2817  remProcs.insert( std::pair< EntityHandle, int >( lconn[0], shared_proc ) );
2818  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lconn[0], rconn[0] ) );
2819  }
2820  found = check_for_parallelinfo( lconn[1], shared_proc, remProcs );
2821  if( !found )
2822  {
2823  remProcs.insert( std::pair< EntityHandle, int >( lconn[1], shared_proc ) );
2824  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lconn[1], rconn[0] ) );
2825  }
2826  }
2827  }
2828 
2829  else
2830  {
2831  for( int j = 0; j < nchd; j++ )
2832  {
2833  // match entityhandles of child edges
2834  bool found = check_for_parallelinfo( lchildEdgs[j], shared_proc, remProcs );
2835 
2836  if( !found )
2837  {
2838  remProcs.insert( std::pair< EntityHandle, int >( lchildEdgs[j], shared_proc ) );
2839  remHandles.insert(
2840  std::pair< EntityHandle, EntityHandle >( lchildEdgs[j], rchildEdgs[nchd - j - 1] ) );
2841  }
2842 
2843  // match entityhandles of child vertices
2844  lconn.clear();
2845  rconn.clear();
2846 
2847  int lidx =
2848  std::find( localEdgeList.begin(), localEdgeList.end(), lchildEdgs[j] ) - localEdgeList.begin();
2849  int ridx = std::find( remEdgeList.begin(), remEdgeList.end(), rchildEdgs[nchd - j - 1] ) -
2850  remEdgeList.begin();
2851 
2852  error = get_data_from_buff( 1, 1, l + 1, lidx, numedges, localEdgeList, lconn );
2853  MB_CHK_ERR( error );
2854  error = get_data_from_buff( 1, 1, l + 1, ridx, numedges, remEdgeList, rconn );
2855  MB_CHK_ERR( error );
2856  found = check_for_parallelinfo( lconn[0], shared_proc, remProcs );
2857 
2858  if( !found )
2859  {
2860  remProcs.insert( std::pair< EntityHandle, int >( lconn[0], shared_proc ) );
2861  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lconn[0], rconn[1] ) );
2862  }
2863 
2864  found = check_for_parallelinfo( lconn[1], shared_proc, remProcs );
2865  if( !found )
2866  {
2867  remProcs.insert( std::pair< EntityHandle, int >( lconn[1], shared_proc ) );
2868  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lconn[1], rconn[1] ) );
2869  }
2870  }
2871  }
2872  }
2873  }
2874 
2875  return MB_SUCCESS;
2876 }
2877 
2878 ErrorCode NestedRefine::decipher_remote_handles_vertex( int shared_proc,
2879  int numverts,
2880  std::vector< EntityHandle >& localVertexList,
2881  std::vector< EntityHandle >& remVertexList,
2882  std::multimap< EntityHandle, int >& remProcs,
2883  std::multimap< EntityHandle, EntityHandle >& remHandles )
2884 {
2885  // LVList = <V> where V = <LV0, LV1, ..,LVL>
2886  // RVList = <V> where V = <LV0', RV1, ..,RVL>, LV0' is the local handles of coarsest vertices
2887  // but in the order in which they appear on the remote/shared proc
2888 
2889  ErrorCode error;
2890 
2891  for( int i = 0; i < numverts; i++ )
2892  {
2893  EntityHandle v = localVertexList[i];
2894  int Rvert_idx =
2895  ( std::find( remVertexList.begin(), remVertexList.begin() + numverts - 1, v ) ) - remVertexList.begin();
2896 
2897  std::vector< EntityHandle > lverts, rverts;
2898  for( int l = 0; l < nlevels; l++ )
2899  {
2900  error = get_data_from_buff( 0, 0, l + 1, i, numverts, localVertexList, lverts );
2901  MB_CHK_ERR( error );
2902  error = get_data_from_buff( 0, 0, l + 1, Rvert_idx, numverts, remVertexList, rverts );
2903  MB_CHK_ERR( error );
2904 
2905  bool found = check_for_parallelinfo( lverts[0], shared_proc, remProcs );
2906  if( !found )
2907  {
2908  remProcs.insert( std::pair< EntityHandle, int >( lverts[0], shared_proc ) );
2909  remHandles.insert( std::pair< EntityHandle, EntityHandle >( lverts[0], rverts[0] ) );
2910  }
2911  }
2912  }
2913 
2914  return MB_SUCCESS;
2915 }
2916 
2917 ErrorCode NestedRefine::update_parallel_tags( std::multimap< EntityHandle, int >& remProcs,
2918  std::multimap< EntityHandle, EntityHandle >& remHandles )
2919 {
2920  ErrorCode error;
2921 
2922  std::vector< int > rprocs;
2923  std::vector< EntityHandle > rhandles;
2924 
2925  std::multimap< EntityHandle, int >::iterator it;
2926  std::pair< std::multimap< EntityHandle, int >::iterator, std::multimap< EntityHandle, int >::iterator > it_procs;
2927  std::pair< std::multimap< EntityHandle, EntityHandle >::iterator,
2928  std::multimap< EntityHandle, EntityHandle >::iterator >
2929  it_handles;
2930 
2931  it = remProcs.begin();
2932  while( it != remProcs.end() )
2933  {
2934  rprocs.clear();
2935  rhandles.clear();
2936 
2937  EntityHandle entity = it->first;
2938  it_procs = remProcs.equal_range( entity );
2939  it_handles = remHandles.equal_range( entity );
2940 
2941  for( std::multimap< EntityHandle, int >::iterator pit = it_procs.first; pit != it_procs.second; pit++ )
2942  rprocs.push_back( pit->second );
2943  for( std::multimap< EntityHandle, EntityHandle >::iterator pit = it_handles.first; pit != it_handles.second;
2944  pit++ )
2945  rhandles.push_back( pit->second );
2946 
2947  error = pcomm->update_remote_data( entity, rprocs, rhandles );
2948  MB_CHK_ERR( error );
2949 
2950  it = remProcs.upper_bound( it->first );
2951  }
2952 
2953  return MB_SUCCESS;
2954 }
2955 
2956 ErrorCode NestedRefine::get_data_from_buff( int listtype,
2957  int datatype,
2958  int level,
2959  int entity_index,
2960  int nentities,
2961  std::vector< EntityHandle >& buffer,
2962  std::vector< EntityHandle >& data )
2963 {
2964  /**
2965  * listtype = 2, 1, 0 for FList (faces), EList (edge) and VList (vertices), respectively
2966  * datatype = 0(entityhandles of entities at level 0 and their children upto nlevels, in the
2967  *case of vertices its the duplicate vertices at subsequent levels), = 1(connectivity for the
2968  *above), = 2(subentities, only case is edges from FList) entity_index = integer index of the
2969  *entity in the buffer nentities = number of entities at the coarsest level i.e., |F0| or |E0|
2970  *or |V0|
2971  *
2972  * Two types of queries:
2973  * 1) Given an entity, find its children at a particular level.
2974  * 2) Given any entity at any level , find its connectivity (or bounding edges)
2975  *
2976  **/
2977 
2978  data.clear();
2979 
2980  if( listtype == 2 ) // FList
2981  {
2982  // FList = <F, FC, FE> where F = <F0, F1, ..,FL>, FC = <FC0, FC1, .., FCL> and FE = <FE0,
2983  // FE1, .., FEL>
2984  if( datatype == 0 ) // requesting child entities
2985  {
2986  EntityType ftype = mbImpl->type_from_handle( buffer[0] );
2987 
2988  int start, end, toadd, prev;
2989  start = end = entity_index;
2990  toadd = prev = nentities;
2991  for( int i = 0; i < level; i++ )
2992  {
2993  int d = get_index_from_degree( level_dsequence[i] );
2994  int nch = refTemplates[ftype - 1][d].total_new_ents;
2995  start = start * nch;
2996  end = end * nch + nch - 1;
2997  if( i < level - 1 )
2998  {
2999  prev = prev * nch;
3000  toadd += prev;
3001  }
3002  }
3003 
3004  start += toadd;
3005  end += toadd;
3006 
3007  int num_child = end - start + 1;
3008  data.reserve( num_child );
3009 
3010  for( int i = start; i <= end; i++ )
3011  {
3012  EntityHandle child = buffer[i];
3013  data.push_back( child );
3014  }
3015  }
3016  else if( datatype == 1 ) // requesting connectivity of an entity
3017  {
3018  EntityType ftype = mbImpl->type_from_handle( buffer[0] );
3019  int nepf = ahf->lConnMap2D[ftype - 2].num_verts_in_face;
3020 
3021  int toadd = nentities, prev = nentities;
3022  for( int i = 0; i < nlevels; i++ )
3023  {
3024  int d = get_index_from_degree( level_dsequence[i] );
3025  int nch = refTemplates[ftype - 1][d].total_new_ents;
3026  prev = prev * nch;
3027  toadd += prev;
3028  }
3029 
3030  for( int i = 0; i < nepf; i++ )
3031  data.push_back( buffer[toadd + nepf * entity_index + i] );
3032  }
3033  else if( datatype == 2 ) // requesting bounding edges of an entity
3034  {
3035  EntityType ftype = mbImpl->type_from_handle( buffer[0] );
3036  int nepf = ahf->lConnMap2D[ftype - 2].num_verts_in_face;
3037 
3038  int toadd = nentities, prev = nentities;
3039  for( int i = 0; i < nlevels; i++ )
3040  {
3041  int d = get_index_from_degree( level_dsequence[i] );
3042  int nch = refTemplates[ftype - 1][d].total_new_ents;
3043  prev = prev * nch;
3044  toadd += prev;
3045  }
3046  toadd += toadd * nepf;
3047 
3048  for( int i = 0; i < nepf; i++ )
3049  data.push_back( buffer[toadd + nepf * entity_index + i] );
3050  }
3051  else
3052  MB_SET_ERR( MB_FAILURE, "Requesting invalid info from buffer for faces" );
3053  }
3054  else if( listtype == 1 ) // EList
3055  {
3056  // EList = <E, EC> where E = <E0, E1, ..,EL> and EC = <EC0, EC1, .., ECL>
3057  if( datatype == 0 ) // requesting child entities
3058  {
3059  int start, end, toadd, prev;
3060  start = end = entity_index;
3061  toadd = prev = nentities;
3062  for( int i = 0; i < level; i++ )
3063  {
3064  int d = get_index_from_degree( level_dsequence[i] );
3065  int nch = refTemplates[MBEDGE - 1][d].total_new_ents;
3066  start = start * nch;
3067  end = end * nch + nch - 1;
3068 
3069  if( i < level - 1 )
3070  {
3071  prev = prev * nch;
3072  toadd += prev;
3073  }
3074  }
3075 
3076  start += toadd;
3077  end += toadd;
3078 
3079  int num_child = end - start + 1;
3080  data.reserve( num_child );
3081 
3082  for( int i = start; i <= end; i++ )
3083  {
3084  EntityHandle child = buffer[i];
3085  data.push_back( child );
3086  }
3087  }
3088  else if( datatype == 1 ) // requesting connectivities of child entities
3089  {
3090  int toadd = nentities, prev = nentities;
3091  for( int i = 0; i < nlevels; i++ )
3092  {
3093  int d = get_index_from_degree( level_dsequence[i] );
3094  int nch = refTemplates[MBEDGE - 1][d].total_new_ents;
3095  prev = prev * nch;
3096  toadd += prev;
3097  }
3098 
3099  data.push_back( buffer[toadd + 2 * entity_index] );
3100  data.push_back( buffer[toadd + 2 * entity_index + 1] );
3101  }
3102  else
3103  MB_SET_ERR( MB_FAILURE, "Requesting invalid info from buffer for edges" );
3104  }
3105  else if( listtype == 0 ) // VList
3106  {
3107  // VList = <V> where V = <V0, V1, ..,VL>
3108  if( datatype == 0 )
3109  {
3110  int idx = level * nentities + entity_index;
3111  data.push_back( buffer[idx] );
3112  }
3113  else
3114  MB_SET_ERR( MB_FAILURE, "Requesting invalid info from buffer for vertices" );
3115  }
3116  else
3117  MB_SET_ERR( MB_FAILURE, "Requesting invalid info from buffer" );
3118 
3119  return MB_SUCCESS;
3120 }
3121 
3122 bool NestedRefine::check_for_parallelinfo( EntityHandle entity, int proc, std::multimap< EntityHandle, int >& remProcs )
3123 {
3124  bool found = false;
3125 
3126  std::pair< std::multimap< EntityHandle, int >::iterator, std::multimap< EntityHandle, int >::iterator > it_hes;
3127  it_hes = remProcs.equal_range( entity );
3128 
3129  for( std::multimap< EntityHandle, int >::iterator it = it_hes.first; it != it_hes.second; ++it )
3130  {
3131  if( it->second == proc )
3132  {
3133  found = true;
3134  break;
3135  }
3136  }
3137 
3138  return found;
3139 }
3140 
3141 ErrorCode NestedRefine::check_for_parallelinfo( EntityHandle entity,
3142  int proc,
3143  std::multimap< EntityHandle, EntityHandle >& remHandles,
3144  std::multimap< EntityHandle, int >& remProcs,
3145  EntityHandle& rhandle )
3146 {
3147  // shared procs for given entity
3148  std::pair< std::multimap< EntityHandle, int >::iterator, std::multimap< EntityHandle, int >::iterator > it_ps;
3149  it_ps = remProcs.equal_range( entity );
3150 
3151  // shared remote handles for given entity
3152  std::pair< std::multimap< EntityHandle, EntityHandle >::iterator,
3153  std::multimap< EntityHandle, EntityHandle >::iterator >
3154  it_hs;
3155  it_hs = remHandles.equal_range( entity );
3156 
3157  std::multimap< EntityHandle, int >::iterator itp;
3158  std::multimap< EntityHandle, EntityHandle >::iterator ith;
3159 
3160  for( itp = it_ps.first, ith = it_hs.first; itp != it_ps.second; ++itp, ++ith )
3161  {
3162  if( itp->second == proc )
3163  {
3164  rhandle = ith->second;
3165  break;
3166  }
3167  }
3168 
3169  return MB_SUCCESS;
3170 }
3171 
3172 #endif
3173 
3174 /**********************************
3175  * Update AHF maps *
3176  * ********************************/
3177 
3179  EntityType type,
3180  int pat_id,
3181  EntityHandle* vbuffer,
3182  EntityHandle* ent_buffer,
3183  int etotal )
3184 {
3185  ErrorCode error;
3186  int nhf = 0, nv = 0, total_new_verts = 0;
3187  int d = get_index_from_degree( deg );
3188 
3189  // Get the number of half-facets
3190  if( type == MBEDGE )
3191  {
3192  nhf = 2;
3193  nv = 2;
3194  total_new_verts = refTemplates[0][d].total_new_verts;
3195  }
3196  else if( type == MBTRI || type == MBQUAD )
3197  {
3198  nhf = ahf->lConnMap2D[type - 2].num_verts_in_face;
3199  nv = nhf;
3200  total_new_verts = refTemplates[pat_id][d].total_new_verts;
3201  }
3202  else if( type == MBTET || type == MBHEX )
3203  {
3204  int index = ahf->get_index_in_lmap( *_incells.begin() );
3207  total_new_verts = refTemplates[pat_id][d].total_new_verts;
3208  }
3209 
3210  std::vector< EntityHandle > ent;
3211  std::vector< int > lid;
3212 
3213  // Update the vertex to half-facet map
3214  for( int i = 0; i < total_new_verts; i++ )
3215  {
3216  ent.clear();
3217  lid.clear();
3218  EntityHandle vid = vbuffer[i + nv];
3219  error = ahf->get_incident_map( type, vid, ent, lid );
3220  MB_CHK_ERR( error );
3221 
3222  if( ent[0] ) continue;
3223 
3224  int id = refTemplates[pat_id][d].v2hf[i + nv][0] - 1;
3225  ent[0] = ent_buffer[id];
3226  lid[0] = refTemplates[pat_id][d].v2hf[i + nv][1];
3227 
3228  error = ahf->set_incident_map( type, vid, ent, lid );
3229  MB_CHK_ERR( error );
3230  }
3231 
3232  // Update the sibling half-facet map
3233  for( int i = 0; i < etotal; i++ )
3234  {
3235  std::vector< EntityHandle > sib_entids( nhf );
3236  std::vector< int > sib_lids( nhf );
3237 
3238  error = ahf->get_sibling_map( type, ent_buffer[i], &sib_entids[0], &sib_lids[0], nhf );
3239  MB_CHK_ERR( error );
3240 
3241  for( int l = 0; l < nhf; l++ )
3242  {
3243  if( sib_entids[l] ) continue;
3244 
3245  // Fill out the sibling values
3246  int id = refTemplates[pat_id][d].ents_opphfs[i][2 * l];
3247  if( id )
3248  {
3249  sib_entids[l] = ent_buffer[id - 1];
3250  sib_lids[l] = refTemplates[pat_id][d].ents_opphfs[i][2 * l + 1];
3251  }
3252  else
3253  {
3254  sib_entids[l] = 0;
3255  sib_lids[l] = 0;
3256  }
3257  }
3258 
3259  error = ahf->set_sibling_map( type, ent_buffer[i], &sib_entids[0], &sib_lids[0], nhf );
3260  MB_CHK_ERR( error );
3261 
3262  for( int l = 0; l < nhf; l++ )
3263  {
3264  if( sib_entids[l] )
3265  {
3266 
3267  EntityHandle set_entid = ent_buffer[i];
3268  int set_lid = l;
3269 
3270  error = ahf->set_sibling_map( type, sib_entids[l], sib_lids[l], set_entid, set_lid );
3271  MB_CHK_ERR( error );
3272  }
3273  }
3274  }
3275  return MB_SUCCESS;
3276 }
3277 
3279  EntityType type,
3280  EntityHandle* vbuffer,
3281  EntityHandle* ent_buffer,
3282  int etotal )
3283 {
3284  ErrorCode error;
3285  assert( type != MBTET );
3286  error = update_local_ahf( deg, type, type - 1, vbuffer, ent_buffer, etotal );
3287  MB_CHK_ERR( error );
3288 
3289  return MB_SUCCESS;
3290 }
3291 
3292 ErrorCode NestedRefine::update_global_ahf( EntityType type, int cur_level, int deg, std::vector< int >* pattern_ids )
3293 {
3294 
3295  ErrorCode error;
3296 
3297  // Get the number of half-facets and number of children of each type
3298  if( type == MBEDGE )
3299  {
3300  assert( pattern_ids == NULL );
3301  error = update_global_ahf_1D( cur_level, deg );
3302  MB_CHK_ERR( error );
3303  }
3304  else if( type == MBTRI || type == MBQUAD )
3305  {
3306  assert( pattern_ids == NULL );
3307  error = update_global_ahf_2D( cur_level, deg );
3308  MB_CHK_ERR( error );
3309  }
3310  else if( type == MBHEX )
3311  {
3312  assert( pattern_ids == NULL );
3313  error = update_global_ahf_3D( cur_level, deg );
3314  MB_CHK_ERR( error );
3315  }
3316  else if( type == MBTET )
3317  {
3318  assert( pattern_ids != NULL );
3319  error = update_global_ahf_3D( cur_level, deg, pattern_ids );
3320  MB_CHK_ERR( error );
3321  }
3322  else
3323  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Requesting AHF update for an unsupported mesh entity type" );
3324 
3325  return MB_SUCCESS;
3326 }
3327 
3328 /*ErrorCode NestedRefine::update_global_ahf(int cur_level, int deg, std::vector<int> &pattern_ids)
3329 {
3330  ErrorCode error;
3331  error = update_global_ahf_3D(cur_level, deg, pattern_ids); MB_CHK_ERR(error);
3332 
3333  return MB_SUCCESS;
3334 }*/
3335 
3337 {
3338  ErrorCode error;
3339  int d = get_index_from_degree( deg );
3340  int nhf, nchilds, nverts_prev, nents_prev;
3341  nhf = 2;
3342  nchilds = refTemplates[0][d].total_new_ents;
3343  if( cur_level )
3344  {
3345  nverts_prev = level_mesh[cur_level - 1].num_verts;
3346  nents_prev = level_mesh[cur_level - 1].num_edges;
3347  }
3348  else
3349  {
3350  nverts_prev = _inverts.size();
3351  nents_prev = _inedges.size();
3352  }
3353 
3354  std::vector< EntityHandle > inci_ent, child_ents;
3355  std::vector< int > inci_lid, child_lids;
3356 
3357  // Update the vertex to half-facet maps for duplicate vertices
3358  for( int i = 0; i < nverts_prev; i++ )
3359  {
3360  inci_ent.clear();
3361  inci_lid.clear();
3362  child_ents.clear();
3363  child_lids.clear();
3364 
3365  // Vertex id in the previous mesh and the current one
3366  EntityHandle vid;
3367  if( cur_level )
3368  vid = level_mesh[cur_level - 1].start_vertex + i;
3369  else
3370  vid = _inverts[i];
3371  EntityHandle cur_vid = level_mesh[cur_level].start_vertex + i;
3372 
3373  // Get the incident half-vert in the previous mesh
3374  error = ahf->get_incident_map( MBEDGE, vid, inci_ent, inci_lid );
3375  MB_CHK_ERR( error );
3376 
3377  // Obtain the corresponding incident child in the current mesh
3378  int lvid = get_local_vid( vid, inci_ent[0], cur_level - 1 );
3379  if( lvid < 0 ) MB_SET_ERR( MB_FAILURE, "did not find local vertex ix " );
3380  int chid = refTemplates[0][d].v2hf[lvid][0] - 1;
3381 
3382  int pid;
3383  if( cur_level )
3384  pid = inci_ent[0] - level_mesh[cur_level - 1].start_edge;
3385  else
3386  pid = inci_ent[0] - *_inedges.begin();
3387 
3388  int ind = nchilds * pid;
3389 
3390  child_ents.push_back( level_mesh[cur_level].start_edge + ind + chid );
3391  child_lids.push_back( refTemplates[0][d].v2hf[lvid][1] );
3392 
3393  error = ahf->set_incident_map( MBEDGE, cur_vid, child_ents, child_lids );
3394  MB_CHK_ERR( error );
3395  }
3396 
3397  // Update the sibling half-facet maps across entities
3398  for( int i = 0; i < nents_prev; i++ )
3399  {
3400  EntityHandle ent;
3401  if( cur_level )
3402  ent = level_mesh[cur_level - 1].start_edge + i;
3403  else
3404  ent = _inedges[i];
3405 
3406  std::vector< EntityHandle > sib_entids( nhf );
3407  std::vector< int > sib_lids( nhf );
3408 
3409  error = ahf->get_sibling_map( MBEDGE, ent, &sib_entids[0], &sib_lids[0], nhf );
3410  MB_CHK_ERR( error );
3411 
3412  int id, idx;
3413 
3414  for( int l = 0; l < nhf; l++ )
3415  {
3416  if( !sib_entids[l] ) continue;
3417 
3418  // Find the child incident on the half-facet
3419  id = refTemplates[0][d].ents_on_pent[l][1] - 1;
3420  idx = nchilds * i;
3421  EntityHandle child_ent = level_mesh[cur_level].start_edge + idx + id;
3422  int ch_lid = l;
3423 
3424  // Find the sibling of the child
3425  std::vector< EntityHandle > sib_childs( nhf );
3426  std::vector< int > sib_chlids( nhf );
3427 
3428  error = ahf->get_sibling_map( MBEDGE, child_ent, &sib_childs[0], &sib_chlids[0], nhf );
3429  MB_CHK_ERR( error );
3430 
3431  // If the sibling already exists, dont do anything
3432  if( sib_childs[ch_lid] ) continue;
3433 
3434  // Get the correponding child of the sibling of the current parent
3435  int psib;
3436  if( cur_level )
3437  psib = sib_entids[l] - level_mesh[cur_level - 1].start_edge;
3438  else
3439  psib = sib_entids[l] - *_inedges.begin();
3440 
3441  int plid = sib_lids[l];
3442 
3443  id = refTemplates[0][d].ents_on_pent[plid][1] - 1;
3444  idx = nchilds * psib;
3445 
3446  EntityHandle psib_child = level_mesh[cur_level].start_edge + idx + id;
3447  int psib_chlid = plid;
3448 
3449  // Set the siblings
3450  sib_childs[ch_lid] = psib_child;
3451  sib_chlids[ch_lid] = psib_chlid;
3452 
3453  error = ahf->set_sibling_map( MBEDGE, child_ent, &sib_childs[0], &sib_chlids[0], nhf );
3454  MB_CHK_ERR( error );
3455  }
3456  }
3457 
3458  return MB_SUCCESS;
3459 }
3460 
3462 {
3463  ErrorCode error;
3464  int d = get_index_from_degree( deg );
3465  int nhf, nchilds, nents_prev;
3466  nhf = 2;
3467  nchilds = refTemplates[0][d].total_new_ents;
3468  if( cur_level )
3469  {
3470  nents_prev = level_mesh[cur_level - 1].num_edges;
3471  }
3472  else
3473  {
3474  nents_prev = _inedges.size();
3475  }
3476 
3477  // Update the sibling half-facet maps across entities
3478 
3479  std::vector< EntityHandle > conn;
3480  for( int i = 0; i < nents_prev; i++ )
3481  {
3482  EntityHandle ent;
3483  if( cur_level )
3484  ent = level_mesh[cur_level - 1].start_edge + i;
3485  else
3486  ent = _inedges[i];
3487 
3488  // Set incident hv maps
3489  conn.clear();
3490  error = get_connectivity( ent, cur_level, conn );
3491  MB_CHK_ERR( error );
3492 
3493  std::vector< EntityHandle > inci_ent, child_ents;
3494  std::vector< int > inci_lid, child_lids;
3495  for( int j = 0; j < 2; j++ )
3496  {
3497  inci_ent.clear();
3498  inci_lid.clear();
3499  child_ents.clear();
3500  child_lids.clear();
3501 
3502  // Get the entityhandle of the vertex from previous level in the current level
3503  EntityHandle cur_vid;
3504  if( cur_level )
3505  cur_vid = level_mesh[cur_level].start_vertex + ( conn[j] - level_mesh[cur_level - 1].start_vertex );
3506  else
3507  cur_vid = level_mesh[cur_level].start_vertex + ( conn[j] - *_inverts.begin() );
3508 
3509  // Obtain the incident half-facet. If exists, then no need to assign another
3510  error = ahf->get_incident_map( MBEDGE, cur_vid, inci_ent, inci_lid );
3511  MB_CHK_ERR( error );
3512  if( inci_ent[0] != 0 ) continue;
3513 
3514  // Get the incident half-facet on the old vertex
3515  error = ahf->get_incident_map( MBEDGE, conn[j], inci_ent, inci_lid );
3516  MB_CHK_ERR( error );
3517 
3518  // Obtain the corresponding incident child in the current mesh
3519  int lvid = get_local_vid( conn[j], inci_ent[0], cur_level - 1 );
3520  if( lvid < 0 ) MB_SET_ERR( MB_FAILURE, "did not find local vertex ix " );
3521  int chid = refTemplates[0][d].v2hf[lvid][0] - 1;
3522 
3523  int pid;
3524  if( cur_level )
3525  pid = inci_ent[0] - level_mesh[cur_level - 1].start_edge;
3526  else
3527  pid = inci_ent[0] - *_inedges.begin();
3528 
3529  int ind = nchilds * pid;
3530 
3531  child_ents.push_back( level_mesh[cur_level].start_edge + ind + chid );
3532  child_lids.push_back( refTemplates[0][d].v2hf[lvid][1] );
3533 
3534  error = ahf->set_incident_map( MBEDGE, cur_vid, child_ents, child_lids );
3535  MB_CHK_ERR( error );
3536  }
3537 
3538  std::vector< EntityHandle > sib_entids( nhf );
3539  std::vector< int > sib_lids( nhf );
3540 
3541  error = ahf->get_sibling_map( MBEDGE, ent, &sib_entids[0], &sib_lids[0], nhf );
3542  MB_CHK_ERR( error );
3543 
3544  int id, idx;
3545 
3546  for( int l = 0; l < nhf; l++ )
3547  {
3548  if( !sib_entids[l] ) continue;
3549 
3550  // Find the child incident on the half-facet
3551  id = refTemplates[0][d].ents_on_pent[l][1] - 1;
3552  idx = nchilds * i;
3553  EntityHandle child_ent = level_mesh[cur_level].start_edge + idx + id;
3554  int ch_lid = l;
3555 
3556  // Find the sibling of the child
3557  std::vector< EntityHandle > sib_childs( nhf );
3558  std::vector< int > sib_chlids( nhf );
3559 
3560  error = ahf->get_sibling_map( MBEDGE, child_ent, &sib_childs[0], &sib_chlids[0], nhf );
3561  MB_CHK_ERR( error );
3562 
3563  // If the sibling already exists, dont do anything
3564  if( sib_childs[ch_lid] ) continue;
3565 
3566  // Get the correponding child of the sibling of the current parent
3567  int psib;
3568  if( cur_level )
3569  psib = sib_entids[l] - level_mesh[cur_level - 1].start_edge;
3570  else
3571  psib = sib_entids[l] - *_inedges.begin();
3572 
3573  int plid = sib_lids[l];
3574 
3575  id = refTemplates[0][d].ents_on_pent[plid][1] - 1;
3576  idx = nchilds * psib;
3577 
3578  EntityHandle psib_child = level_mesh[cur_level].start_edge + idx + id;
3579  int psib_chlid = plid;
3580 
3581  // Set the siblings
3582  sib_childs[ch_lid] = psib_child;
3583  sib_chlids[ch_lid] = psib_chlid;
3584 
3585  error = ahf->set_sibling_map( MBEDGE, child_ent, &sib_childs[0], &sib_chlids[0], nhf );
3586  MB_CHK_ERR( error );
3587  }
3588  }
3589 
3590  return MB_SUCCESS;
3591 }
3592 
3594 {
3595  ErrorCode error;
3596  error = ahf->determine_sibling_halfverts( level_mesh[cur_level].verts, level_mesh[cur_level].edges );
3597  MB_CHK_ERR( error );
3598 
3599  error = ahf->determine_incident_halfverts( level_mesh[cur_level].edges );
3600  MB_CHK_ERR( error );
3601 
3602  return MB_SUCCESS;
3603 }
3604 
3606 {
3607  ErrorCode error;
3608 
3609  EntityType type = mbImpl->type_from_handle( *_infaces.begin() );
3610  int nhf, nchilds, nverts_prev, nents_prev;
3611 
3612  nhf = ahf->lConnMap2D[type - 2].num_verts_in_face;
3613  int d = get_index_from_degree( deg );
3614  nchilds = refTemplates[type - 1][d].total_new_ents;
3615 
3616  if( cur_level )
3617  {
3618  nverts_prev = level_mesh[cur_level - 1].num_verts;
3619  nents_prev = level_mesh[cur_level - 1].num_faces;
3620  }
3621  else
3622  {
3623  nverts_prev = _inverts.size();
3624  nents_prev = _infaces.size();
3625  }
3626 
3627  std::vector< EntityHandle > inci_ent, child_ents;
3628  std::vector< int > inci_lid, child_lids;
3629 
3630  // Update the vertex to half-edge maps for old/duplicate vertices
3631  for( int i = 0; i < nverts_prev; i++ )
3632  {
3633  inci_ent.clear();
3634  inci_lid.clear();
3635  child_ents.clear();
3636  child_lids.clear();
3637 
3638  // Vertex id in the previous mesh
3639  EntityHandle vid;
3640  if( cur_level )
3641  vid = level_mesh[cur_level - 1].start_vertex + i;
3642  else
3643  vid = _inverts[i];
3644  EntityHandle cur_vid = level_mesh[cur_level].start_vertex + i;
3645 
3646  // Get the incident half-vert in the previous mesh
3647  error = ahf->get_incident_map( type, vid, inci_ent, inci_lid );
3648  MB_CHK_ERR( error );
3649 
3650  // Obtain the corresponding incident child in the current mesh
3651  for( int j = 0; j < (int)inci_ent.size(); j++ )
3652  {
3653  int lvid = get_local_vid( vid, inci_ent[j], cur_level - 1 );
3654  if( lvid < 0 ) MB_SET_ERR( MB_FAILURE, "did not find local vertex ix " );
3655  int chid = refTemplates[type - 1][d].v2hf[lvid][0] - 1;
3656 
3657  int pid;
3658  if( cur_level )
3659  pid = inci_ent[j] - level_mesh[cur_level - 1].start_face;
3660  else
3661  pid = inci_ent[j] - *_infaces.begin();
3662 
3663  int ind = nchilds * pid;
3664 
3665  child_ents.push_back( level_mesh[cur_level].start_face + ind + chid );
3666  child_lids.push_back( refTemplates[type - 1][d].v2hf[lvid][1] );
3667  }
3668  error = ahf->set_incident_map( type, cur_vid, child_ents, child_lids );
3669  MB_CHK_ERR( error );
3670  }
3671 
3672  EntityHandle fedge[2];
3673 
3674  // Update the sibling half-facet maps across entities
3675  for( int i = 0; i < nents_prev; i++ )
3676  {
3677  EntityHandle ent;
3678  if( cur_level )
3679  ent = level_mesh[cur_level - 1].start_face + i;
3680  else
3681  ent = _infaces[i];
3682 
3683  std::vector< EntityHandle > fid_conn;
3684  error = get_connectivity( ent, cur_level, fid_conn );
3685  if( MB_SUCCESS != error ) return error;
3686 
3687  std::vector< EntityHandle > sib_entids( nhf );
3688  std::vector< int > sib_lids( nhf );
3689 
3690  error = ahf->get_sibling_map( type, ent, &sib_entids[0], &sib_lids[0], nhf );
3691  MB_CHK_ERR( error );
3692 
3693  int id, idx;
3694 
3695  for( int l = 0; l < nhf; l++ )
3696  {
3697  if( !sib_entids[l] ) continue;
3698 
3699  int nidx = ahf->lConnMap2D[type - 2].next[l];
3700  fedge[0] = fid_conn[l];
3701  fedge[1] = fid_conn[nidx];
3702 
3703  EntityHandle sfid = sib_entids[l];
3704  int slid = sib_lids[l];
3705 
3706  std::vector< EntityHandle > conn;
3707  error = get_connectivity( sfid, cur_level, conn );
3708  if( MB_SUCCESS != error ) return error;
3709 
3710  bool orient = true;
3711  nidx = ahf->lConnMap2D[type - 2].next[slid];
3712  if( ( fedge[1] == conn[slid] ) && ( fedge[0] == conn[nidx] ) ) orient = false;
3713 
3714  if( orient ) assert( ( fedge[0] == conn[slid] ) && ( fedge[1] == conn[nidx] ) );
3715 
3716  // Find the childrens incident on the half-facet
3717  int nch = refTemplates[type - 1][d].ents_on_pent[l][0];
3718  idx = nchilds * i;
3719 
3720  // Loop over all the incident childrens
3721  for( int k = 0; k < nch; k++ )
3722  {
3723  id = refTemplates[type - 1][d].ents_on_pent[l][k + 1] - 1;
3724  EntityHandle child_ent = level_mesh[cur_level].start_face + idx + id;
3725  int child_lid = l;
3726 
3727  // Find the sibling of the child
3728  EntityHandle child_sibent;
3729  int child_siblid;
3730  error = ahf->get_sibling_map( type, child_ent, child_lid, child_sibent, child_siblid );
3731  MB_CHK_ERR( error );
3732 
3733  if( child_sibent != 0 ) continue;
3734 
3735  // Get the correponding child of the sibling of the current parent
3736  int psib;
3737  if( cur_level )
3738  psib = sfid - level_mesh[cur_level - 1].start_face;
3739  else
3740  psib = sfid - *_infaces.begin();
3741 
3742  int plid = slid;
3743 
3744  if( orient )
3745  id = refTemplates[type - 1][d].ents_on_pent[plid][k + 1] - 1;
3746  else
3747  id = refTemplates[type - 1][d].ents_on_pent[plid][nch - k] - 1;
3748 
3749  int sidx = nchilds * psib;
3750 
3751  EntityHandle psib_child = level_mesh[cur_level].start_face + sidx + id;
3752  int psib_chlid = plid;
3753 
3754  // Set the siblings
3755  error = ahf->set_sibling_map( type, child_ent, child_lid, psib_child, psib_chlid );
3756  MB_CHK_ERR( error );
3757  }
3758  }
3759  }
3760 
3761  return MB_SUCCESS;
3762 }
3763 
3765 {
3766  ErrorCode error;
3767  int d = get_index_from_degree( deg );
3768  EntityType type = mbImpl->type_from_handle( *_infaces.begin() );
3769  int nhf, nchilds, nents_prev;
3770  nhf = ahf->lConnMap2D[type - 2].num_verts_in_face;
3771  nchilds = refTemplates[type - 1][d].total_new_ents;
3772 
3773  if( cur_level )
3774  nents_prev = level_mesh[cur_level - 1].num_faces;
3775  else
3776  nents_prev = _infaces.size();
3777 
3778  EntityHandle fedge[2];
3779 
3780  // Update the sibling half-facet maps across entities
3781  for( int i = 0; i < nents_prev; i++ )
3782  {
3783  EntityHandle ent;
3784  if( cur_level )
3785  ent = level_mesh[cur_level - 1].start_face + i;
3786  else
3787  ent = _infaces[i];
3788 
3789  std::vector< EntityHandle > fid_conn;
3790  error = get_connectivity( ent, cur_level, fid_conn );
3791  if( MB_SUCCESS != error ) return error;
3792 
3793  std::vector< EntityHandle > inci_ent, child_ents;
3794  std::vector< int > inci_lid, child_lids;
3795 
3796  // Set incident half-edges
3797  for( int j = 0; j < nhf; j++ )
3798  {
3799  inci_ent.clear();
3800  inci_lid.clear();
3801  child_ents.clear();
3802  child_lids.clear();
3803  EntityHandle cur_vid;
3804  if( cur_level )
3805  cur_vid = level_mesh[cur_level].start_vertex + ( fid_conn[j] - level_mesh[cur_level - 1].start_vertex );
3806  else
3807  cur_vid = level_mesh[cur_level].start_vertex + ( fid_conn[j] - *_inverts.begin() );
3808 
3809  // Obtain the incident half-facet. If exists, then no need to assign another
3810  error = ahf->get_incident_map( type, cur_vid, inci_ent, inci_lid );
3811  MB_CHK_ERR( error );
3812  if( inci_ent[0] != 0 ) continue;
3813 
3814  // Get the incident half-facet on the old vertex
3815  error = ahf->get_incident_map( type, fid_conn[j], inci_ent, inci_lid );
3816  MB_CHK_ERR( error );
3817 
3818  // Obtain the corresponding incident child in the current mesh
3819  for( int k = 0; k < (int)inci_ent.size(); k++ )
3820  {
3821  int lvid = get_local_vid( fid_conn[j], inci_ent[k], cur_level - 1 );
3822  if( lvid < 0 ) MB_SET_ERR( MB_FAILURE, "did not find local vertex ix " );
3823  int chid = refTemplates[type - 1][d].v2hf[lvid][0] - 1;
3824 
3825  int pid;
3826  if( cur_level )
3827  pid = inci_ent[k] - level_mesh[cur_level - 1].start_face;
3828  else
3829  pid = inci_ent[k] - *_infaces.begin();
3830 
3831  int ind = nchilds * pid;
3832 
3833  child_ents.push_back( level_mesh[cur_level].start_face + ind + chid );
3834  child_lids.push_back( refTemplates[type - 1][d].v2hf[lvid][1] );
3835  }
3836 
3837  error = ahf->set_incident_map( type, cur_vid, child_ents, child_lids );
3838  MB_CHK_ERR( error );
3839  }
3840 
3841  // Set sibling half-edges
3842  std::vector< EntityHandle > sib_entids( nhf );
3843  std::vector< int > sib_lids( nhf );
3844 
3845  error = ahf->get_sibling_map( type, ent, &sib_entids[0], &sib_lids[0], nhf );
3846  MB_CHK_ERR( error );
3847 
3848  int id, idx;
3849 
3850  for( int l = 0; l < nhf; l++ )
3851  {
3852  if( !sib_entids[l] ) continue;
3853 
3854  int nidx = ahf->lConnMap2D[type - 2].next[l];
3855  fedge[0] = fid_conn[l];
3856  fedge[1] = fid_conn[nidx];
3857 
3858  EntityHandle sfid = sib_entids[l];
3859  int slid = sib_lids[l];
3860 
3861  std::vector< EntityHandle > conn;
3862  error = get_connectivity( sfid, cur_level, conn );
3863  MB_CHK_ERR( error );
3864 
3865  assert( (int)conn.size() > nidx && (int)conn.size() > slid );
3866 
3867  bool orient = true;
3868  nidx = ahf->lConnMap2D[type - 2].next[slid];
3869  if( ( fedge[1] == conn[slid] ) && ( fedge[0] == conn[nidx] ) ) orient = false;
3870 
3871  if( orient ) assert( ( fedge[0] == conn[slid] ) && ( fedge[1] == conn[nidx] ) );
3872 
3873  // Find the childrens incident on the half-facet
3874  int nch = refTemplates[type - 1][d].ents_on_pent[l][0];
3875  idx = nchilds * i;
3876 
3877  // Loop over all the incident childrens
3878  for( int k = 0; k < nch; k++ )
3879  {
3880  id = refTemplates[type - 1][d].ents_on_pent[l][k + 1] - 1;
3881  EntityHandle child_ent = level_mesh[cur_level].start_face + idx + id;
3882  int child_lid = l;
3883 
3884  // Find the sibling of the child
3885  EntityHandle child_sibent;
3886  int child_siblid;
3887  error = ahf->get_sibling_map( type, child_ent, child_lid, child_sibent, child_siblid );
3888  MB_CHK_ERR( error );
3889 
3890  if( child_sibent != 0 ) continue;
3891 
3892  // Get the correponding child of the sibling of the current parent
3893  int psib;
3894  if( cur_level )
3895  psib = sfid - level_mesh[cur_level - 1].start_face;
3896  else
3897  psib = sfid - *_infaces.begin();
3898 
3899  int plid = slid;
3900 
3901  if( orient )
3902  id = refTemplates[type - 1][d].ents_on_pent[plid][k + 1] - 1;
3903  else
3904  id = refTemplates[type - 1][d].ents_on_pent[plid][nch - k] - 1;
3905 
3906  int sidx = nchilds * psib;
3907 
3908  EntityHandle psib_child = level_mesh[cur_level].start_face + sidx + id;
3909  int psib_chlid = plid;
3910 
3911  // Set the siblings
3912  error = ahf->set_sibling_map( type, child_ent, child_lid, psib_child, psib_chlid );
3913  MB_CHK_ERR( error );
3914  }
3915  }
3916  }
3917 
3918  return MB_SUCCESS;
3919 }
3920 
3921 ErrorCode NestedRefine::update_global_ahf_3D( int cur_level, int deg, std::vector< int >* pattern_ids )
3922 {
3923  ErrorCode error;
3924  int nvpc, ne, nhf, nchilds, nverts_prev, nents_prev;
3925 
3926  EntityType type = mbImpl->type_from_handle( *_incells.begin() );
3927  int index = ahf->get_index_in_lmap( *_incells.begin() );
3928  int d = get_index_from_degree( deg );
3929 
3933  nchilds = refTemplates[type - 1][d].total_new_ents;
3934 
3935  if( cur_level )
3936  {
3937  nverts_prev = level_mesh[cur_level - 1].num_verts;
3938  nents_prev = level_mesh[cur_level - 1].num_cells;
3939  }
3940  else
3941  {
3942  nverts_prev = _inverts.size();
3943  nents_prev = _incells.size();
3944  }
3945 
3946  std::vector< EntityHandle > inci_ent, child_ents;
3947  std::vector< int > inci_lid, child_lids;
3948 
3949  // Step 1: Update the V2HF maps for old/duplicate vertices
3950  for( int i = 0; i < nverts_prev; i++ )
3951  {
3952  inci_ent.clear();
3953  inci_lid.clear();
3954  child_ents.clear();
3955  child_lids.clear();
3956 
3957  // Vertex id in the previous mesh
3958  EntityHandle vid;
3959  if( cur_level )
3960  vid = level_mesh[cur_level - 1].start_vertex + i;
3961  else
3962  vid = _inverts[i];
3963  EntityHandle cur_vid = level_mesh[cur_level].start_vertex + i;
3964 
3965  // Get the incident half-vert in the previous mesh
3966  error = ahf->get_incident_map( type, vid, inci_ent, inci_lid );
3967  MB_CHK_ERR( error );
3968 
3969  // Obtain the corresponding incident child in the current mesh
3970  for( int j = 0; j < (int)inci_ent.size(); j++ )
3971  {
3972  int lvid = get_local_vid( vid, inci_ent[j], cur_level - 1 );
3973  if( lvid < 0 ) MB_SET_ERR( MB_FAILURE, "did not find local vertex ix " );
3974  int chid = refTemplates[type - 1][d].v2hf[lvid][0] - 1;
3975 
3976  int pid;
3977  if( cur_level )
3978  pid = inci_ent[j] - level_mesh[cur_level - 1].start_cell;
3979  else
3980  pid = inci_ent[j] - *_incells.begin();
3981 
3982  int ind = nchilds * pid;
3983 
3984  // EntityHandle child_ent = level_mesh[cur_level].start_cell + ind+chid ;
3985  // int child_lid = refTemplates[type-1][d].v2hf[lvid][1];
3986  child_ents.push_back( level_mesh[cur_level].start_cell + ind + chid );
3987  child_lids.push_back( refTemplates[type - 1][d].v2hf[lvid][1] );
3988  }
3989 
3990  error = ahf->set_incident_map( type, cur_vid, child_ents, child_lids );
3991  MB_CHK_ERR( error );
3992  }
3993 
3994  // error = ahf->determine_incident_halffaces( level_mesh[cur_level].cells);MB_CHK_ERR(error);
3995 
3996  // Step 2: Update SIBHFS maps
3997  for( int i = 0; i < nents_prev; i++ )
3998  {
3999  EntityHandle ent;
4000  if( cur_level )
4001  ent = level_mesh[cur_level - 1].start_cell + i;
4002  else
4003  ent = _incells[i];
4004 
4005  std::vector< EntityHandle > sib_entids( nhf );
4006  std::vector< int > sib_lids( nhf );
4007 
4008  error = ahf->get_sibling_map( type, ent, &sib_entids[0], &sib_lids[0], nhf );
4009  MB_CHK_ERR( error );
4010 
4011  int id, idx;
4012 
4013  for( int l = 0; l < nhf; l++ )
4014  {
4015 
4016  if( !sib_entids[l] ) continue;
4017 
4018  // Get the number of children incident on this half-face
4019  int pat_id;
4020  if( type == MBTET )
4021  pat_id = ( *pattern_ids )[i];
4022  else
4023  pat_id = type - 1;
4024  int nch = refTemplates[pat_id][d].ents_on_pent[l][0];
4025 
4026  // Get the order of children indices incident on this half-face
4027  std::vector< int > id_sib( nch );
4028  for( int k = 0; k < nch; k++ )
4029  id_sib[k] = 0;
4030 
4031  error = reorder_indices( cur_level, deg, ent, l, sib_entids[l], sib_lids[l], 1, &id_sib[0] );
4032  MB_CHK_ERR( error );
4033 
4034  // Get the parent index of the sibling cell
4035  int psib;
4036  if( cur_level )
4037  psib = sib_entids[l] - level_mesh[cur_level - 1].start_cell;
4038  else
4039  psib = sib_entids[l] - *_incells.begin();
4040 
4041  int plid = sib_lids[l];
4042  int sidx = nchilds * psib;
4043  int sibpat_id;
4044  if( type == MBTET )
4045  sibpat_id = ( *pattern_ids )[psib];
4046  else
4047  sibpat_id = type - 1;
4048 
4049  // Loop over all the childs incident on the working half-face
4050  idx = nchilds * i;
4051 
4052  for( int k = 0; k < nch; k++ )
4053  {
4054  id = refTemplates[pat_id][d].ents_on_pent[l][k + 1] - 1;
4055  EntityHandle child_ent = level_mesh[cur_level].start_cell + idx + id;
4056  int child_lid = l;
4057 
4058  // Find the sibling of the working child
4059  EntityHandle child_sibent;
4060  int child_siblid;
4061  error = ahf->get_sibling_map( type, child_ent, child_lid, child_sibent, child_siblid );
4062  MB_CHK_ERR( error );
4063 
4064  if( child_sibent != 0 ) continue;
4065 
4066  // Get the correponding child of the sibling of the current parent
4067  // We have already computed the order the children on incident corresponding to the
4068  // working half-face
4069  id = refTemplates[sibpat_id][d].ents_on_pent[plid][id_sib[k]] - 1;
4070 
4071  EntityHandle psib_child = level_mesh[cur_level].start_cell + sidx + id;
4072  int psib_chlid = plid;
4073 
4074  // Set the siblings of children incident on current half-face
4075  error = ahf->set_sibling_map( type, child_ent, child_lid, psib_child, psib_chlid );
4076  MB_CHK_ERR( error );
4077 
4078  // Set the sibling of the sibling of the children to the children
4079  error = ahf->set_sibling_map( type, psib_child, psib_chlid, child_ent, child_lid );
4080  MB_CHK_ERR( error );
4081  }
4082  }
4083 
4084  // Loop over edges to check if there are any non-manifold edges. If there are then the v2hfs
4085  // map should be updated for the new vertices on it.
4086  const EntityHandle* conn;
4087  error = mbImpl->get_connectivity( ent, conn, nvpc );
4088  MB_CHK_ERR( error );
4089 
4090  int nv = refTemplates[type - 1][d].nv_edge; //#verts on each edge
4091  for( int l = 0; l < ne; l++ )
4092  {
4093  id = ahf->lConnMap3D[index].e2v[l][0];
4094  EntityHandle v_start = conn[id];
4095  id = ahf->lConnMap3D[index].e2v[l][1];
4096  EntityHandle v_end = conn[id];
4097 
4098  bool visited = false;
4099 
4100  std::vector< EntityHandle > inci_ent1, inci_ent2;
4101  std::vector< int > inci_lid1, inci_lid2;
4102  error = ahf->get_incident_map( type, v_start, inci_ent1, inci_lid1 );
4103  MB_CHK_ERR( error );
4104  error = ahf->get_incident_map( type, v_end, inci_ent2, inci_lid2 );
4105  MB_CHK_ERR( error );
4106 
4107  if( inci_ent1.size() > 1 && inci_ent2.size() > 1 )
4108  {
4109  std::vector< EntityHandle > cell_comps;
4110  std::vector< int > leid_comps;
4111 
4112  error = ahf->get_up_adjacencies_edg_3d_comp( ent, l, cell_comps, &leid_comps );
4113  MB_CHK_ERR( error );
4114 
4115  int ncomps = cell_comps.size();
4116  std::vector< EntityHandle > edgverts;
4117  std::vector< EntityHandle > compchildents( nv * ncomps );
4118  std::vector< int > compchildlfids( nv * ncomps );
4119 
4120  for( int s = 0; s < nv * ncomps; s++ )
4121  {
4122  compchildents[s] = 0;
4123  compchildlfids[s] = 0;
4124  }
4125 
4126  for( int j = 0; j < (int)cell_comps.size(); j++ )
4127  {
4128  int ind;
4129  if( cur_level )
4130  ind = level_mesh[cur_level - 1].cells.index( cell_comps[j] );
4131  else
4132  ind = _incells.index( cell_comps[j] );
4133 
4134  for( int k = 0; k < nv; k++ )
4135  {
4136  int chid = refTemplates[type - 1][d].ents_on_vedge[leid_comps[j]][3 * k] - 1;
4137  int lfid = refTemplates[type - 1][d].ents_on_vedge[leid_comps[j]][3 * k + 1];
4138  int lvid = refTemplates[type - 1][d].ents_on_vedge[leid_comps[j]][3 * k + 2];
4139 
4140  EntityHandle childcell = level_mesh[cur_level].start_cell + ind * nchilds + chid;
4141 
4142  const EntityHandle* econn;
4143  error = mbImpl->get_connectivity( childcell, econn, nvpc );
4144  MB_CHK_ERR( error );
4145 
4146  EntityHandle vert = econn[lvid];
4147 
4148  if( ahf->check_nonmanifold_vertices( type, vert ) )
4149  {
4150  visited = true;
4151  break;
4152  }
4153 
4154  if( edgverts.empty() )
4155  {
4156  edgverts.push_back( vert );
4157  compchildents[0] = childcell;
4158  compchildlfids[0] = lfid;
4159  }
4160  else
4161  {
4162  std::vector< EntityHandle >::iterator it;
4163  it = find( edgverts.begin(), edgverts.end(), vert );
4164  int indx = it - edgverts.begin();
4165 
4166  if( it == edgverts.end() )
4167  {
4168  edgverts.push_back( vert );
4169  compchildents[k * ncomps] = childcell;
4170  compchildlfids[k * ncomps] = lfid;
4171  }
4172  else
4173  {
4174  compchildents[indx * ncomps + j] = childcell;
4175  compchildlfids[indx * ncomps + j] = lfid;
4176  }
4177  }
4178  }
4179  }
4180 
4181  if( visited )
4182  {
4183  break;
4184  }
4185 
4186  // Set the incident half-facet map
4187  for( int k = 0; k < nv; k++ )
4188  {
4189  std::vector< EntityHandle > set_childents;
4190  std::vector< int > set_childlfids;
4191  for( int j = 0; j < ncomps; j++ )
4192  {
4193  set_childents.push_back( compchildents[k * ncomps + j] );
4194  set_childlfids.push_back( compchildlfids[k * ncomps + j] );
4195  }
4196 
4197  error = ahf->set_incident_map( type, edgverts[k], set_childents, set_childlfids );
4198  MB_CHK_ERR( error );
4199  }
4200  }
4201  }
4202  }
4203 
4204  return MB_SUCCESS;
4205 }
4206 
4208  int deg,
4209  int lfid,
4210  int leid,
4211  std::vector< int >& child_ids,
4212  std::vector< int >& child_lvids )
4213 {
4214  int index = ahf->get_index_in_lmap( *_incells.begin() );
4215  int d = get_index_from_degree( deg );
4216 
4217  // int lv0 = ahf->lConnMap3D[index].e2v[leid][0];
4218  // int lv1 = ahf->lConnMap3D[index].e2v[leid][1];
4219  int nvpc = ahf->lConnMap3D[index].num_verts_in_cell;
4220 
4221  int nv = refTemplates[type - 1][d].nv_edge;
4222  int nch = refTemplates[type - 1][d].ents_on_pent[lfid][0];
4223 
4224  for( int i = 0; i < nch; i++ )
4225  {
4226  int id = refTemplates[type - 1][d].ents_on_pent[lfid][i + 1] - 1;
4227  for( int j = 0; j < nvpc; j++ )
4228  {
4229  int lv = refTemplates[type - 1][d].ents_conn[id][j];
4230  for( int k = 0; k < nv; k++ )
4231  {
4232  if( lv == refTemplates[type - 1][d].vert_on_edges[leid][k] )
4233  {
4234  child_ids.push_back( id );
4235  child_lvids.push_back( j );
4236  }
4237  }
4238  }
4239  }
4240 
4241  return MB_SUCCESS;
4242 }
4243 
4244 /* **********************************
4245  * * Boundary Functions *
4246  ************************************/
4247 
4249 {
4250  ErrorCode error;
4251  EntityHandle sibents[27];
4252  int siblids[27];
4253  std::vector< EntityHandle > ent;
4254  std::vector< int > lid;
4255 
4256  int nhf;
4257  if( elementype == MBEDGE )
4258  nhf = 2;
4259  else if( ( elementype == MBTRI ) || ( elementype == MBQUAD ) )
4261  else if( ( elementype == MBTET ) || ( elementype == MBHEX ) )
4262  {
4263  int idx = ahf->get_index_in_lmap( *_incells.begin() );
4264  nhf = ahf->lConnMap3D[idx].num_faces_in_cell;
4265  }
4266  else
4267  MB_SET_ERR( MB_FAILURE, "Requesting vertex boundary information for an unsupported entity type" );
4268 
4269  error = ahf->get_incident_map( elementype, vertex, ent, lid );
4270  MB_CHK_ERR( error );
4271  error = ahf->get_sibling_map( elementype, ent[0], &sibents[0], &siblids[0], nhf );
4272  MB_CHK_ERR( error );
4273 
4274  return ( sibents[lid[0]] == 0 );
4275 }
4276 
4278 {
4279  ErrorCode error;
4280  bool is_border = false;
4281  if( meshdim == 1 ) // The edge has a vertex on the boundary in the curve mesh
4282  {
4283  EntityHandle sibents[2];
4284  int siblids[2];
4285  error = ahf->get_sibling_map( MBEDGE, entity, &sibents[0], &siblids[0], 2 );
4286  MB_CHK_ERR( error );
4287  for( int i = 0; i < 2; i++ )
4288  {
4289  if( sibents[i] == 0 )
4290  {
4291  is_border = true;
4292  break;
4293  }
4294  }
4295  }
4296  else if( meshdim == 2 ) // The edge is on the boundary of the 2d mesh
4297  {
4298  std::vector< EntityHandle > adjents;
4299  error = ahf->get_up_adjacencies_2d( entity, adjents );
4300  MB_CHK_ERR( error );
4301  if( adjents.size() == 1 ) is_border = true;
4302  }
4303  else if( meshdim == 3 ) // The edge is part of a face on the boundary of the 3d mesh
4304  {
4305  std::vector< EntityHandle > adjents;
4306  std::vector< int > leids;
4307  error = ahf->get_up_adjacencies_edg_3d( entity, adjents, &leids );
4308  MB_CHK_ERR( error );
4309  assert( !adjents.empty() );
4310 
4311  int index = ahf->get_index_in_lmap( adjents[0] );
4312  int nhf = ahf->lConnMap3D[index].num_faces_in_cell;
4313 
4314  for( int i = 0; i < (int)adjents.size(); i++ )
4315  {
4316  EntityHandle sibents[6];
4317  int siblids[6];
4318  error = ahf->get_sibling_map( elementype, adjents[0], &sibents[0], &siblids[0], nhf );
4319  MB_CHK_ERR( error );
4320  for( int k = 0; k < 2; k++ )
4321  {
4322  int hf = ahf->lConnMap3D[index].e2hf[leids[0]][k];
4323  if( sibents[hf] == 0 )
4324  {
4325  is_border = true;
4326  break;
4327  }
4328  }
4329  }
4330  }
4331  return is_border;
4332 }
4333 
4335 {
4336  ErrorCode error;
4337  bool is_border = false;
4338 
4339  if( meshdim == 1 )
4340  MB_SET_ERR( MB_FAILURE, "Requesting boundary information for a face entity type on a curve mesh" );
4341  else if( meshdim == 2 ) // The face has a local edge on the boundary of the 2d mesh
4342  {
4343  EntityHandle sibents[4];
4344  int siblids[4];
4345  int nepf = ahf->lConnMap2D[elementype - 2].num_verts_in_face;
4346  error = ahf->get_sibling_map( elementype, entity, &sibents[0], &siblids[0], nepf );
4347  MB_CHK_ERR( error );
4348 
4349  for( int i = 0; i < nepf; i++ )
4350  {
4351  if( sibents[i] == 0 )
4352  {
4353  is_border = true;
4354  break;
4355  }
4356  }
4357  }
4358  else if( meshdim == 3 ) // The face lies on the boundary of the 3d mesh
4359  {
4360  std::vector< EntityHandle > adjents;
4361  error = ahf->get_up_adjacencies_face_3d( entity, adjents );
4362  MB_CHK_ERR( error );
4363  if( adjents.size() == 1 ) is_border = true;
4364  }
4365  return is_border;
4366 }
4367 
4369 {
4370  if( meshdim != 3 )
4371  MB_SET_ERR( MB_FAILURE, "Requesting boundary information for a cell entity type on a curve or surface mesh" );
4372 
4373  bool is_border = false;
4374  int index = ahf->get_index_in_lmap( *_incells.begin() );
4375  int nfpc = ahf->lConnMap3D[index].num_faces_in_cell;
4376  EntityHandle sibents[6];
4377  int siblids[6];
4378 
4379  ErrorCode error = ahf->get_sibling_map( elementype, entity, &sibents[0], &siblids[0], nfpc );
4380  MB_CHK_ERR( error );
4381 
4382  for( int i = 0; i < nfpc; i++ )
4383  {
4384  if( sibents[i] == 0 )
4385  {
4386  is_border = true;
4387  break;
4388  }
4389  }
4390  return is_border;
4391 }
4392 
4393 /* **********************************
4394  * Helper Functions *
4395  ************************************/
4397 {
4398  ErrorCode error;
4399 
4400  if( cur_level )
4401  {
4402  int nverts_prev = level_mesh[cur_level - 1].num_verts;
4403  for( int i = 0; i < nverts_prev; i++ )
4404  {
4405  level_mesh[cur_level].coordinates[0][i] = level_mesh[cur_level - 1].coordinates[0][i];
4406  level_mesh[cur_level].coordinates[1][i] = level_mesh[cur_level - 1].coordinates[1][i];
4407  level_mesh[cur_level].coordinates[2][i] = level_mesh[cur_level - 1].coordinates[2][i];
4408  }
4409  }
4410  else // Copy the vertices from the input mesh
4411  {
4412  int nverts_in = _inverts.size();
4413  std::vector< double > vcoords( 3 * nverts_in );
4414  error = mbImpl->get_coords( _inverts, &vcoords[0] );
4415  MB_CHK_ERR( error );
4416 
4417  for( int i = 0; i < nverts_in; i++ )
4418  {
4419  level_mesh[cur_level].coordinates[0][i] = vcoords[3 * i];
4420  level_mesh[cur_level].coordinates[1][i] = vcoords[3 * i + 1];
4421  level_mesh[cur_level].coordinates[2][i] = vcoords[3 * i + 2];
4422  }
4423  }
4424  return MB_SUCCESS;
4425  // To add: Map from old vertices to new duplicates: NOT NEEDED
4426 }
4427 
4429  int cur_level,
4430  int deg,
4431  std::vector< EntityHandle >& trackvertsC_edg,
4432  std::vector< EntityHandle >& trackvertsC_face,
4433  EntityHandle* vbuffer )
4434 {
4435  // The vertices in the vbuffer are added to appropriate edges and faces of cells that are
4436  // incident on the working cell.
4437  ErrorCode error;
4438 
4439  EntityHandle cstart_prev;
4440  if( cur_level )
4441  cstart_prev = level_mesh[cur_level - 1].start_cell;
4442  else
4443  cstart_prev = *_incells.begin();
4444 
4445  EntityType cell_type = mbImpl->type_from_handle( cstart_prev );
4446  int cindex = cell_type - 1;
4447  int d = get_index_from_degree( deg );
4448 
4449  int nve = refTemplates[cindex][d].nv_edge;
4450  int nvf = refTemplates[cindex][d].nv_face;
4451 
4452  int index = ahf->get_index_in_lmap( *( _incells.begin() ) );
4453  int nepc = ahf->lConnMap3D[index].num_edges_in_cell;
4454  int nfpc = ahf->lConnMap3D[index].num_faces_in_cell;
4455 
4456  // Step 1: Add the vertices on an edge of the working cell to tracking array of incident cells.
4457  for( int i = 0; i < nepc; i++ )
4458  {
4459  // Add the vertices to edges of the current cell
4460  for( int j = 0; j < nve; j++ )
4461  {
4462  int id = refTemplates[cindex][d].vert_on_edges[i][j];
4463  int idx = cid - cstart_prev;
4464  int aid = idx * nve * nepc + nve * i + j;
4465 
4466  if( !trackvertsC_edg[aid] ) trackvertsC_edg[aid] = vbuffer[id];
4467  }
4468 
4469  // Obtain all the incident cells
4470  std::vector< EntityHandle > inc_cids;
4471  std::vector< int > inc_leids, inc_orient;
4472 
4473  error = ahf->get_up_adjacencies_edg_3d( cid, i, inc_cids, &inc_leids, &inc_orient );
4474  MB_CHK_ERR( error );
4475 
4476  if( inc_cids.size() == 1 ) continue;
4477 
4478  // Add the vertices to the edges of the incident cells
4479  for( int k = 0; k < (int)inc_cids.size(); k++ )
4480  {
4481  if( inc_cids[k] == cid ) continue;
4482 
4483  int idx = inc_cids[k] - cstart_prev;
4484 
4485  if( inc_orient[k] ) // Same edge direction as the current edge
4486  {
4487  for( int j = 0; j < nve; j++ )
4488  {
4489  int id = refTemplates[cindex][d].vert_on_edges[i][j];
4490  int aid = idx * nve * nepc + nve * inc_leids[k] + j;
4491 
4492  if( !trackvertsC_edg[aid] ) trackvertsC_edg[aid] = vbuffer[id];
4493  }
4494  }
4495  else
4496  {
4497  for( int j = 0; j < nve; j++ )
4498  {
4499  int id = refTemplates[cindex][d].vert_on_edges[i][nve - j - 1];
4500  int aid = idx * nve * nepc + nve * inc_leids[k] + j;
4501 
4502  if( !trackvertsC_edg[aid] ) trackvertsC_edg[aid] = vbuffer[id];
4503  }
4504  }
4505  }
4506  }
4507 
4508  // Step 2: Add the vertices on a face of the working cell to tracking array of incident cells.
4509  if( nvf )
4510  {
4511 
4512  for( int i = 0; i < nfpc; i++ )
4513  {
4514  // Add vertices to the tracking array of vertices on faces for the current cell
4515  std::vector< EntityHandle > face_vbuf( nvf, 0 );
4516  for( int j = 0; j < nvf; j++ )
4517  {
4518  int id = refTemplates[cindex][d].vert_on_faces[i][j];
4519  int idx = cid - cstart_prev;
4520  int aid = idx * nvf * nfpc + nvf * i + j;
4521 
4522  if( !trackvertsC_face[aid] ) trackvertsC_face[aid] = vbuffer[id];
4523 
4524  face_vbuf[j] = vbuffer[id];
4525  }
4526 
4527  // Obtain all the incident cells
4528  std::vector< EntityHandle > sib_cids;
4529  std::vector< int > sib_lfids;
4530  error = ahf->get_up_adjacencies_face_3d( cid, i, sib_cids, &sib_lfids );
4531  MB_CHK_ERR( error );
4532 
4533  if( sib_cids.size() == 1 ) continue;
4534 
4535  // Reorder the vertex local ids incident on the half-face
4536  std::vector< int > id_sib( nvf );
4537  for( int k = 0; k < nvf; k++ )
4538  id_sib[k] = 0;
4539 
4540  error = reorder_indices( cur_level, deg, sib_cids[1], sib_lfids[1], cid, i, 0, &id_sib[0] );
4541  MB_CHK_ERR( error );
4542 
4543  // Add vertices to the tracking array of vertices on faces for the sibling cell of the
4544  // current cell
4545  for( int j = 0; j < nvf; j++ )
4546  {
4547  int idx = sib_cids[1] - cstart_prev;
4548  int aid = idx * nvf * nfpc + nvf * sib_lfids[1] + j;
4549 
4550  if( !trackvertsC_face[aid] ) trackvertsC_face[aid] = face_vbuf[id_sib[j] - 1];
4551  }
4552  }
4553  }
4554  return MB_SUCCESS;
4555 }
4556 
4558  int deg,
4559  EntityHandle cell,
4560  int lfid,
4561  EntityHandle sib_cell,
4562  int sib_lfid,
4563  int index,
4564  int* id_sib )
4565 {
4566  // Reorders the indices of either vertices or children cell local ids to match with order of the
4567  // given cell and a local face. index = 0 : vertices,
4568  // = 1 : face
4569 
4570  assert( deg == 2 || deg == 3 );
4571 
4572  ErrorCode error;
4573  int idx = ahf->get_index_in_lmap( *_incells.begin() );
4574  int nvF = ahf->lConnMap3D[idx].hf2v_num[lfid];
4575  int nco = permutation[nvF - 3].num_comb;
4576 
4577  if( !index && ( ( nvF == 3 && deg == 3 ) || ( nvF == 4 && deg == 2 ) ) )
4578  {
4579  id_sib[0] = 1;
4580  }
4581  else
4582  {
4583  // Get connectivity of the cell and its sibling cell
4584  std::vector< EntityHandle > conn, sib_conn;
4585  error = get_connectivity( cell, cur_level, conn );
4586  MB_CHK_ERR( error );
4587 
4588  error = get_connectivity( sib_cell, cur_level, sib_conn );
4589  MB_CHK_ERR( error );
4590 
4591  // Get the connectivity of the local face in the cell and its sibling
4592  std::vector< EntityHandle > lface( nvF );
4593  std::vector< EntityHandle > lface_sib( nvF );
4594  for( int i = 0; i < nvF; i++ )
4595  {
4596  int id = ahf->lConnMap3D[idx].hf2v[lfid][i];
4597  lface[i] = conn[id];
4598 
4599  id = ahf->lConnMap3D[idx].hf2v[sib_lfid][i];
4600  lface_sib[i] = sib_conn[id];
4601  }
4602 
4603  // Find the combination
4604  int c = 0;
4605  for( int i = 0; i < nco; i++ )
4606  {
4607  int count = 0;
4608  for( int j = 0; j < nvF; j++ )
4609  {
4610  int id = permutation[nvF - 3].comb[i][j];
4611  if( lface[j] == lface_sib[id] ) count += 1;
4612  }
4613 
4614  if( count == nvF )
4615  {
4616  c = i;
4617  break;
4618  }
4619  }
4620 
4621  if( c > nco ) MB_SET_ERR( MB_FAILURE, "Getting a combination number more than currently supported" );
4622 
4623  // Get the ordered indices
4624  if( ( ( !index ) && ( nvF == 4 ) && ( deg == 3 ) ) || ( deg == 2 ) )
4625  {
4626  for( int i = 0; i < 4; i++ )
4627  id_sib[i] = permutation[nvF - 3].porder2[c][i];
4628  }
4629  else
4630  {
4631  for( int i = 0; i < 9; i++ )
4632  id_sib[i] = permutation[nvF - 3].porder3[c][i];
4633  }
4634  }
4635 
4636  return MB_SUCCESS;
4637 }
4638 
4640  EntityHandle* face1_conn,
4641  EntityHandle* face2_conn,
4642  int nvF,
4643  std::vector< int >& lemap,
4644  std::vector< int >& vidx,
4645  int* leorient )
4646 {
4647  // Given the connectivities of two faces, get the permuted indices w.r.t first face.
4648  // Step 1: First find the orientation
4649  int nco = permutation[nvF - 3].num_comb;
4650  int c = 0;
4651  for( int i = 0; i < nco; i++ )
4652  {
4653  int count = 0;
4654  for( int j = 0; j < nvF; j++ )
4655  {
4656  int id = permutation[nvF - 3].comb[i][j];
4657  if( face1_conn[j] == face2_conn[id] ) count += 1;
4658  }
4659 
4660  if( count == nvF )
4661  {
4662  c = i;
4663  break;
4664  }
4665  }
4666 
4667  if( c > nco ) MB_SET_ERR( MB_FAILURE, "Getting a combination number more than currently supported" );
4668 
4669  // Add the corresponding local edges
4670  lemap.reserve( nvF );
4671  for( int i = 0; i < nvF; i++ )
4672  {
4673  lemap.push_back( permutation[nvF - 3].lemap[c][i] );
4674  }
4675  if( leorient ) leorient[0] = permutation[nvF - 3].orient[c];
4676 
4677  if( nvF == 3 && deg == 2 ) return MB_SUCCESS;
4678 
4679  if( ( nvF == 3 && deg == 3 ) || ( nvF == 4 && deg == 2 ) )
4680  {
4681  vidx.push_back( 1 );
4682  }
4683  else if( nvF == 4 && deg == 3 )
4684  {
4685  for( int i = 0; i < 4; i++ )
4686  vidx.push_back( permutation[nvF - 3].porder2[c][i] );
4687  }
4688 
4689  return MB_SUCCESS;
4690 }
4691 
4692 ErrorCode NestedRefine::reorder_indices( int deg, int nvF, int comb, int* childfid_map )
4693 {
4694  // Given connectivities of two faces and a degree, get the permuted indices of the children
4695  // faces w.r.t first face.
4696 
4697  assert( deg == 2 || deg == 3 );
4698 
4699  // Get the ordered indices
4700  if( deg == 2 )
4701  {
4702  for( int i = 0; i < 4; i++ )
4703  childfid_map[i] = permutation[nvF - 3].porder2[comb][i];
4704  }
4705  else
4706  {
4707  for( int i = 0; i < 9; i++ )
4708  childfid_map[i] = permutation[nvF - 3].porder3[comb][i];
4709  }
4710 
4711  return MB_SUCCESS;
4712 }
4713 
4715  EntityHandle* face2_conn,
4716  int nvF,
4717  int* conn_map,
4718  int& comb,
4719  int* orient )
4720 {
4721  // Given connectivities of two faces and a degree, get the permuted indices of the children
4722  // faces w.r.t first face.
4723 
4724  // Step 1: First find the combination
4725  int nco = permutation[nvF - 3].num_comb;
4726  int c = 0;
4727  for( int i = 0; i < nco; i++ )
4728  {
4729  int count = 0;
4730  for( int j = 0; j < nvF; j++ )
4731  {
4732  int id = permutation[nvF - 3].comb[i][j];
4733  if( face1_conn[j] == face2_conn[id] ) count += 1;
4734  }
4735 
4736  if( count == nvF )
4737  {
4738  c = i;
4739  break;
4740  }
4741  }
4742 
4743  if( c > nco ) MB_SET_ERR( MB_FAILURE, "Getting a combination number more than currently supported" );
4744 
4745  comb = c;
4746 
4747  if( orient ) orient[0] = permutation[nvF - 3].orient[c];
4748 
4749  for( int j = 0; j < nvF; j++ )
4750  {
4751  conn_map[j] = permutation[nvF - 3].comb[c][j];
4752  }
4753 
4754  return MB_SUCCESS;
4755 }
4756 
4757 ErrorCode NestedRefine::count_subentities( EntityHandle set, int cur_level, int* nedges, int* nfaces )
4758 {
4759  ErrorCode error;
4760 
4761  if( cur_level >= 0 )
4762  {
4763  Range edges, faces, cells;
4764 
4765  error = mbImpl->get_entities_by_dimension( set, 1, edges );
4766  MB_CHK_ERR( error );
4767 
4768  error = mbImpl->get_entities_by_dimension( set, 2, faces );
4769  MB_CHK_ERR( error );
4770 
4771  error = mbImpl->get_entities_by_dimension( set, 3, cells );
4772  MB_CHK_ERR( error );
4773 
4774  error = ahf->count_subentities( edges, faces, cells, nedges, nfaces );
4775  MB_CHK_ERR( error );
4776  }
4777  else
4778  {
4779  error = ahf->count_subentities( _inedges, _infaces, _incells, nedges, nfaces );
4780  MB_CHK_ERR( error );
4781  }
4782 
4783  return MB_SUCCESS;
4784 }
4785 
4786 ErrorCode NestedRefine::get_octahedron_corner_coords( int cur_level, int deg, EntityHandle* vbuffer, double* ocoords )
4787 {
4788  int lid[6] = { 0, 0, 0, 0, 0, 0 };
4789 
4790  if( deg == 2 )
4791  {
4792  lid[0] = 5;
4793  lid[1] = 8;
4794  lid[2] = 9;
4795  lid[3] = 6;
4796  lid[4] = 4;
4797  lid[5] = 7;
4798  }
4799  else if( deg == 3 )
4800  {
4801  lid[0] = 19;
4802  lid[1] = 16;
4803  lid[2] = 18;
4804  lid[3] = 9;
4805  lid[4] = 4;
4806  lid[5] = 10;
4807  }
4808 
4809  EntityHandle vstart = level_mesh[cur_level].start_vertex;
4810 
4811  for( int i = 0; i < 6; i++ )
4812  {
4813  EntityHandle vid = vbuffer[lid[i]];
4814  ocoords[3 * i] = level_mesh[cur_level].coordinates[0][vid - vstart];
4815  ocoords[3 * i + 1] = level_mesh[cur_level].coordinates[1][vid - vstart];
4816  ocoords[3 * i + 2] = level_mesh[cur_level].coordinates[2][vid - vstart];
4817  }
4818 
4819  return MB_SUCCESS;
4820 }
4821 
4822 int NestedRefine::find_shortest_diagonal_octahedron( int cur_level, int deg, EntityHandle* vbuffer )
4823 {
4824  ErrorCode error;
4825  double coords[18];
4826  error = get_octahedron_corner_coords( cur_level, deg, vbuffer, coords );
4827  if( error != MB_SUCCESS ) MB_SET_ERR( MB_FAILURE, "Error in obtaining octahedron corner coordinates" );
4828 
4829  int diag_map[6] = { 1, 3, 2, 4, 5, 0 };
4830  double length = std::numeric_limits< double >::max();
4831 
4832  int diag = 0;
4833  double x, y, z;
4834  x = y = z = 0;
4835 
4836  for( int d = 0; d < 3; d++ )
4837  {
4838  int id1 = diag_map[2 * d];
4839  int id2 = diag_map[2 * d + 1];
4840  x = coords[3 * id1] - coords[3 * id2];
4841  y = coords[3 * id1 + 1] - coords[3 * id2 + 1];
4842  z = coords[3 * id1 + 2] - coords[3 * id2 + 2];
4843  double dlen = sqrt( x * x + y * y + z * z );
4844  if( dlen < length )
4845  {
4846  length = dlen;
4847  diag = d + 1;
4848  }
4849  }
4850 
4851  return diag;
4852 }
4853 
4855 {
4856  ErrorCode error;
4857  // Given a vertex, find its local id in the given entity
4858  std::vector< EntityHandle > conn;
4859 
4860  error = get_connectivity( ent, level + 1, conn );
4861  if( error != MB_SUCCESS ) MB_SET_ERR( MB_FAILURE, "Error in getting connectivity of the requested entity" );
4862 
4863  int lid = -1;
4864  for( int i = 0; i < (int)conn.size(); i++ )
4865  {
4866  if( conn[i] == vid )
4867  {
4868  lid = i;
4869  break;
4870  }
4871  }
4872  if( lid < 0 ) MB_SET_ERR( MB_FAILURE, "Error in getting local vertex id in the given entity" );
4873  return lid;
4874 }
4875 
4877 {
4878  int d = deg_index.find( degree )->second;
4879  return d;
4880 }
4881 
4882 /*
4883 ErrorCode NestedRefine::print_maps_1D(int level)
4884 {
4885  ErrorCode error;
4886  int nv, ne;
4887  nv = level_mesh[level].num_verts;
4888  ne = level_mesh[level].num_edges;
4889 
4890  EntityHandle start_edge = level_mesh[level].start_edge;
4891 
4892  //V2HV
4893  std::cout<<"<V2HV_EID, V2HV_LVID>"<<std::endl;
4894  for (int i=0; i<nv; i++)
4895  {
4896  EntityHandle eid=0;
4897  int lvid=0;
4898  EntityHandle vid = level_mesh[level].start_vertex+i;
4899  error = ahf->get_incident_map(MBEDGE, vid, eid, lvid); MB_CHK_ERR(error);
4900 
4901  std::cout<<"For vertex = "<<vid<<"::Incident halfvertex "<<eid<<" "<<lvid<<std::endl;
4902  }
4903 
4904  //SIBHVS
4905  std::cout<<"start_edge = "<<start_edge<<std::endl;
4906  std::cout<<"<SIBHVS_EID,SIBHVS_LVID>"<<std::endl;
4907  for (int i=0; i<ne; i++)
4908  {
4909  EntityHandle ent = start_edge+i;
4910 
4911  EntityHandle eid[2]; int lvid[2];
4912  error = ahf->get_sibling_map(MBEDGE, ent, &eid[0], &lvid[0], 2); MB_CHK_ERR(error);
4913  std::cout<<"<"<<eid[0]<<","<<lvid[0]<<">"<<" "<<"<"<<eid[1]<<","<<lvid[1]<<">"<<std::endl;
4914  }
4915 
4916  return MB_SUCCESS;
4917 }
4918 
4919 ErrorCode NestedRefine::print_maps_2D(int level, EntityType type)
4920 {
4921  ErrorCode error;
4922  int nv, nf;
4923  nv = level_mesh[level].num_verts;
4924  nf = level_mesh[level].num_faces;
4925 
4926  EntityHandle start_face = level_mesh[level].start_face;
4927 
4928  //V2HV
4929  std::cout<<"<V2HE_FID, V2HE_LEID>"<<std::endl;
4930  for (int i=0; i<nv; i++)
4931  {
4932  EntityHandle fid=0;
4933  int leid=0;
4934  EntityHandle vid = level_mesh[level].start_vertex+i;
4935  error = ahf->get_incident_map(type, vid, fid, leid); MB_CHK_ERR(error);
4936 
4937  std::cout<<"For vertex = "<<vid<<"::Incident halfedge "<<fid<<" "<<leid<<std::endl;
4938  }
4939 
4940  //SIBHES
4941  std::cout<<"start_face = "<<start_face<<std::endl;
4942  std::cout<<"<SIBHES_FID,SIBHES_LEID>"<<std::endl;
4943  EntityType ftype = mbImpl->type_from_handle(*_infaces.begin());
4944  int nepf = ahf->lConnMap2D[ftype-2].num_verts_in_face;
4945 
4946  EntityHandle *fid = new EntityHandle[nepf];
4947  int *leid = new int[nepf];
4948 
4949  for (int i=0; i<nf; i++)
4950  {
4951  for (int j=0; j<nepf; j++)
4952  {
4953  fid[j] = 0;
4954  leid[j] = 0;
4955  }
4956 
4957  EntityHandle ent = start_face+i;
4958  error = ahf->get_sibling_map(type, ent, fid, leid, nepf); MB_CHK_ERR(error);
4959 
4960  for (int j=0; j<nepf; j++){
4961  std::cout<<"<"<<fid[j]<<","<<leid[j]<<">"<<" ";
4962  }
4963  std::cout<<std::endl;
4964  }
4965 
4966  delete [] fid;
4967  delete [] leid;
4968 
4969  return MB_SUCCESS;
4970 }
4971 
4972 ErrorCode NestedRefine::print_maps_3D(int level, EntityType type)
4973 {
4974  ErrorCode error;
4975  int nv, nc;
4976  nv = level_mesh[level].num_verts;
4977  nc = level_mesh[level].num_cells;
4978  EntityHandle start_cell = level_mesh[level].start_cell;
4979 
4980  //V2HF
4981  std::cout<<"<V2HF_CID, V2HF_LFID>"<<std::endl;
4982  for (int i=0; i<nv; i++)
4983  {
4984  EntityHandle cid=0;
4985  int lfid=0;
4986  EntityHandle vid = level_mesh[level].start_vertex+i;
4987  error = ahf->get_incident_map(type, vid, cid, lfid); MB_CHK_ERR(error);
4988 
4989  std::cout<<"For vertex = "<<vid<<"::Incident halfface "<<cid<<" "<<lfid<<std::endl;
4990  }
4991 
4992  //SIBHFS
4993  std::cout<<"start_cell = "<<start_cell<<std::endl;
4994  std::cout<<"<SIBHFS_CID,SIBHFS_LFID>"<<std::endl;
4995  int index = ahf->get_index_in_lmap(start_cell);
4996  int nfpc = ahf->lConnMap3D[index].num_faces_in_cell;
4997 
4998  EntityHandle *cid = new EntityHandle[nfpc];
4999  int *lfid = new int[nfpc];
5000  for (int i=0; i<nc; i++)
5001  {
5002  for (int k=0; k<nfpc; k++)
5003  {
5004  cid[k] = 0;
5005  lfid[k] = 0;
5006  }
5007 
5008  EntityHandle ent = start_cell+i;
5009  error = ahf->get_sibling_map(type, ent, cid, lfid, nfpc); MB_CHK_ERR(error);
5010 
5011  for (int j=0; j<nfpc; j++){
5012  std::cout<<"<"<<cid[j]<<","<<lfid[j]<<">"<<" ";
5013  }
5014  std::cout<<std::endl;
5015  }
5016 
5017  delete [] cid;
5018  delete [] lfid;
5019 
5020  return MB_SUCCESS;
5021 }
5022 
5023 */
5024 } // namespace moab