Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
WriteUtil.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #ifdef WIN32
17 #pragma warning( disable : 4786 )
18 #endif
19 
20 #include "WriteUtil.hpp"
21 #include "moab/Core.hpp"
22 #include "moab/Error.hpp"
23 #include "SequenceManager.hpp"
24 #include "ElementSequence.hpp"
25 #include "VertexSequence.hpp"
26 #include "AEntityFactory.hpp"
27 #include "MBTagConventions.hpp"
29 #include "MeshSetSequence.hpp"
30 
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <cerrno>
34 #include <cassert>
35 #include <iostream>
36 
37 #ifdef WIN32
38 #define stat _stat
39 #else
40 #include <unistd.h>
41 #endif
42 
43 namespace moab
44 {
45 
46 WriteUtil::WriteUtil( Core* mdb ) : WriteUtilIface(), mMB( mdb ) {}
47 
48 //! Check if the specified file already exists.
49 //! Returns MB_SUCCESS if file does not exist, MB_ALREADY_ALLOCATED
50 //! if file does exist, or MB_FAILURE for some other error condition.
51 ErrorCode WriteUtil::check_doesnt_exist( const char* file_name )
52 {
53  struct stat s;
54  if( 0 == stat( file_name, &s ) )
55  {
56  MB_SET_ERR( MB_ALREADY_ALLOCATED, file_name << ": file already exists" );
57  }
58  else if( errno == ENOENT )
59  return MB_SUCCESS;
60  else
61  return MB_FAILURE;
62 }
63 
64 //! Gather all entities in the mesh, or in the sets specified
66  /**< range in which entities are returned */
67  const EntityHandle* ent_sets,
68  /**< entity sets whose contents are to be gathered */
69  const int num_sets
70  /**< number of sets in list */
71 )
72 {
73  ErrorCode rval = MB_SUCCESS;
74  if( !ent_sets || num_sets == 0 )
75  {
76  rval = mMB->get_entities_by_handle( 0, all_ents );
77  }
78  else
79  {
80  for( int i = 0; i < num_sets; i++ )
81  {
82  ErrorCode tmp_rval = mMB->get_entities_by_handle( ent_sets[i], all_ents );
83  if( MB_SUCCESS != tmp_rval ) rval = tmp_rval;
84  }
85  }
86 
87  return rval;
88 }
89 
90 ErrorCode WriteUtil::get_node_coords( const int num_arrays,
91  const int num_nodes,
92  const Range& entities,
93  Tag node_id_tag,
94  const int start_node_id,
95  std::vector< double* >& arrays )
96 {
97  // Check the data coming into the function
98  // Dimension should be proper
99  if( num_arrays < 1 || num_arrays > 3 ) return MB_FAILURE;
100 
101  // There should be some entities
102  // if (entities.empty())
103  // return MB_FAILURE;
104  // The above necessitates annoying special cases for files
105  // w/out vertices (e.g. a kD-tree). Return NULL array
106  // pointers instead. - kraftcheck, 3-14-08
107  if( entities.empty() )
108  {
109  arrays.clear();
110  arrays.resize( num_arrays, NULL );
111  return MB_SUCCESS;
112  }
113 
114  // Memory should already be allocated for us
115  int tmp_num_arrays = 0;
116  for( unsigned int i = 0; i < 3; i++ )
117  if( i + 1 <= arrays.size() && NULL != arrays[i] ) tmp_num_arrays++;
118  if( 0 == tmp_num_arrays ) return MB_FAILURE;
119 
120  // Get coordinate data
121  ErrorCode result = mMB->get_coords( entities, num_arrays < 1 || arrays.size() < 1 ? NULL : arrays[0],
122  num_arrays < 2 || arrays.size() < 2 ? NULL : arrays[1],
123  num_arrays < 3 || arrays.size() < 3 ? NULL : arrays[2] );
124 
125  if( 0 == node_id_tag || MB_SUCCESS != result ) return result;
126 
127  // Now assign tags
128  std::vector< int > ids( num_nodes );
129  int node_id = start_node_id;
130  for( int i = 0; i < num_nodes; i++ )
131  ids[i] = node_id++;
132  result = mMB->tag_set_data( node_id_tag, entities, &ids[0] );
133 
134  return result;
135 }
136 
137 ErrorCode WriteUtil::get_node_coords( const int which_array, /* 0->X, 1->Y, 2->Z, -1->all */
139  const Range::const_iterator& end,
140  const size_t output_array_len,
141  double* const output_array )
142 {
143  // Check the data coming into the function
144  // Dimension should be proper
145  if( which_array < -1 || which_array > 2 ) return MB_FAILURE;
146 
147  // There should be some entities
148  if( iter == end ) return MB_FAILURE;
149 
150  // Memory should already be allocated for us
151  if( NULL == output_array || 0 == output_array_len ) return MB_FAILURE;
152 
153  // Sequence iterators
154  TypeSequenceManager::iterator seq_iter, seq_end;
155  seq_iter = mMB->sequence_manager()->entity_map( MBVERTEX ).begin();
156  seq_end = mMB->sequence_manager()->entity_map( MBVERTEX ).end();
157 
158  // Loop over range, getting coordinate value
159  double* output_iter = output_array;
160  double* const output_end = output_array + output_array_len;
161  while( iter != end )
162  {
163  // Find the sequence containing the current handle
164  while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
165  ++seq_iter;
166  if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
167 
168  // Determine how much of the sequence we want.
169  Range::pair_iterator pair( iter );
170  Range::const_iterator prev( end );
171  --prev;
172  EntityHandle range_end = pair->second;
173  EntityHandle sequence_end = ( *seq_iter )->end_handle();
174  EntityHandle end_handle = range_end > sequence_end ? sequence_end : range_end;
175  if( end_handle > *prev ) end_handle = *prev;
176  EntityHandle count = end_handle - *iter + 1;
177 
178  // Get offset in sequence to start at
179  assert( *iter >= ( *seq_iter )->start_handle() );
180  EntityHandle offset = *iter - ( *seq_iter )->start_handle();
181 
182  // Get coordinate arrays from sequence
183  double* coord_array[3];
184  static_cast< VertexSequence* >( *seq_iter )
185  ->get_coordinate_arrays( coord_array[0], coord_array[1], coord_array[2] );
186 
187  // Copy data to output buffer
188  if( -1 != which_array )
189  {
190  if( output_iter + count > output_end ) return MB_FAILURE;
191  memcpy( output_iter, coord_array[which_array] + offset, count * sizeof( double ) );
192  output_iter += count;
193  }
194  else
195  {
196  if( output_iter + 3 * count > output_end ) return MB_FAILURE;
197  for( unsigned int i = 0; i < count; i++ )
198  {
199  *output_iter = coord_array[0][i + offset];
200  output_iter++;
201  *output_iter = coord_array[1][i + offset];
202  output_iter++;
203  *output_iter = coord_array[2][i + offset];
204  output_iter++;
205  }
206  }
207 
208  // Iterate
209  iter += count;
210  }
211 
212  return MB_SUCCESS;
213 }
214 
216  const int verts_per_element,
217  Tag node_id_tag,
218  const Range& elements,
219  Tag element_id_tag,
220  int start_element_id,
221  int* element_array,
222  bool add_sizes )
223 {
224  // Check the data we got
225  if( num_elements < 1 ) return MB_FAILURE;
226  if( verts_per_element < 1 ) return MB_FAILURE;
227  if( elements.empty() ) return MB_FAILURE;
228  if( !element_array ) return MB_FAILURE;
229 
230  Range::const_iterator range_iter = elements.begin();
231  Range::const_iterator range_iter_end = elements.end();
232 
233  TypeSequenceManager::iterator seq_iter, seq_iter_end;
234  EntityType current_type = TYPE_FROM_HANDLE( *range_iter );
235 
236  seq_iter = mMB->sequence_manager()->entity_map( current_type ).begin();
237  seq_iter_end = mMB->sequence_manager()->entity_map( current_type ).end();
238 
239  // Let's find the entity sequence which holds the first entity
240  TypeSequenceManager::iterator seq_iter_lookahead = seq_iter;
241  ++seq_iter_lookahead;
242  for( ; seq_iter_lookahead != seq_iter_end && ( *seq_iter_lookahead )->start_handle() < *range_iter; )
243  {
244  ++seq_iter;
245  ++seq_iter_lookahead;
246  }
247 
248  // A look ahead iterator
249  Range::const_iterator range_iter_lookahead = range_iter;
250 
251  // Our main loop
252  for( ; range_iter != range_iter_end && seq_iter != seq_iter_end; /* ++ is handled in loop*/ )
253  {
254  // Find a range that fits in the current entity sequence
255  for( ; range_iter_lookahead != range_iter_end && *range_iter_lookahead <= ( *seq_iter )->end_handle();
256  ++range_iter_lookahead )
257  {
258  }
259 
260  if( current_type != TYPE_FROM_HANDLE( *range_iter ) )
261  {
262  current_type = TYPE_FROM_HANDLE( *range_iter );
263  seq_iter = mMB->sequence_manager()->entity_map( current_type ).begin();
264  seq_iter_end = mMB->sequence_manager()->entity_map( current_type ).end();
265 
266  // Let's find the entity sequence which holds the first entity of this type
267  TypeSequenceManager::const_iterator seq_iter_lookahead2 = seq_iter;
268  ++seq_iter_lookahead2;
269  for( ; seq_iter_lookahead2 != seq_iter_end && ( *seq_iter_lookahead2 )->start_handle() < *range_iter; )
270  {
271  ++seq_iter;
272  ++seq_iter_lookahead2;
273  }
274  }
275 
276  int i = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
277 
278  // Get the connectivity array
279  EntityHandle* conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
280 
281  EntityHandle start_handle = ( *seq_iter )->start_handle();
282 
283  for( Range::const_iterator tmp_iter = range_iter; tmp_iter != range_iter_lookahead; ++tmp_iter )
284  {
285  // Set the element id tag
286  mMB->tag_set_data( element_id_tag, &*tmp_iter, 1, &start_element_id );
287  ++start_element_id;
288 
289  if( add_sizes ) *element_array++ = i;
290 
291  // For each node
292  for( int j = 0; j < i; j++ )
293  {
294  EntityHandle node = *( conn_array + j + i * ( *tmp_iter - start_handle ) );
295  mMB->tag_get_data( node_id_tag, &node, 1, element_array );
296  element_array++;
297  }
298  }
299 
300  // Go to the next entity sequence
301  ++seq_iter;
302  // Start with the next entities
303  range_iter = range_iter_lookahead;
304  }
305 
306  return MB_SUCCESS;
307 }
308 
310  const Range::const_iterator& end,
311  const int vertices_per_elem,
312  Tag node_id_tag,
313  const size_t elem_array_size,
314  int* const element_array,
315  bool add_sizes )
316 {
317  // Check the data we got
318  if( iter == end ) return MB_FAILURE;
319  if( vertices_per_elem < 1 ) return MB_FAILURE;
320  if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
321 
322  // Sequence iterators
323  TypeSequenceManager::const_iterator seq_iter, seq_end;
324 
325  // loop over range, getting coordinate value
326  EntityType current_type = MBMAXTYPE;
327  int* output_iter = element_array;
328  int* const output_end = element_array + elem_array_size;
329  while( iter != end )
330  {
331  // Make sure we have the right sequence list (and get the sequence
332  // list for the first iteration.)
333  EntityType type = TYPE_FROM_HANDLE( *iter );
334  if( type != current_type )
335  {
336  if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
337  seq_iter = mMB->sequence_manager()->entity_map( type ).begin();
338  seq_end = mMB->sequence_manager()->entity_map( type ).end();
339  current_type = type;
340  }
341 
342  // Find the sequence containing the current handle
343  while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
344  ++seq_iter;
345  if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
346 
347  // Get the connectivity array
348  EntityHandle* conn_array = NULL;
349  int conn_size = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
350  conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
351 
352  // Determine how much of the sequence we want.
353  Range::pair_iterator pair( iter );
354  Range::const_iterator prev( end );
355  --prev;
356  EntityHandle range_end = pair->second;
357  EntityHandle sequence_end = ( *seq_iter )->end_handle();
358  EntityHandle end_handle = range_end > sequence_end ? sequence_end : range_end;
359  if( end_handle > *prev ) end_handle = *prev;
360  EntityHandle count = end_handle - *iter + 1;
361 
362  // Get offset in sequence to start at
363  assert( *iter >= ( *seq_iter )->start_handle() );
364  EntityHandle offset = *iter - ( *seq_iter )->start_handle();
365 
366  // Make sure sufficient space in output array
367  if( ( !add_sizes && output_iter + ( count * conn_size ) > output_end ) ||
368  ( add_sizes && output_iter + ( count * ( conn_size + 1 ) ) > output_end ) )
369  return MB_FAILURE;
370 
371  // If the nodes per element match, do in one call
372  conn_array += ( conn_size * offset );
373  if( vertices_per_elem == conn_size && !add_sizes )
374  {
375  ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, count * conn_size, output_iter );
376  if( MB_SUCCESS != rval ) return rval;
377 
378  output_iter += count * conn_size;
379  }
380  // Otherwise need to do one at a time
381  else
382  {
383  int min = vertices_per_elem > conn_size ? conn_size : vertices_per_elem;
384  for( EntityHandle i = 0; i < count; ++i )
385  {
386  *output_iter++ = min;
387  ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, min, output_iter );
388  if( MB_SUCCESS != rval ) return rval;
389 
390  output_iter += min;
391  conn_array += conn_size;
392 
393  if( vertices_per_elem > conn_size )
394  { // Need to pad
395  memset( output_iter, 0, sizeof( int ) * ( vertices_per_elem - conn_size ) );
396  output_iter += ( vertices_per_elem - conn_size );
397  }
398  }
399  }
400 
401  iter += count;
402  }
403 
404  return MB_SUCCESS;
405 }
406 
408  const Range::const_iterator& end,
409  const int vertices_per_elem,
410  const size_t elem_array_size,
411  EntityHandle* const element_array )
412 {
413  // Check the data we got
414  if( iter == end ) return MB_FAILURE;
415  if( vertices_per_elem < 1 ) return MB_FAILURE;
416  if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
417 
418  // Sequence iterators
419  TypeSequenceManager::const_iterator seq_iter, seq_end;
420 
421  // Loop over range, getting coordinate value
422  EntityType current_type = MBMAXTYPE;
423  EntityHandle* output_iter = element_array;
424  EntityHandle* const output_end = element_array + elem_array_size;
425  while( iter != end )
426  {
427  // Make sure we have the right sequence list (and get the sequence
428  // list for the first iteration.)
429  EntityType type = TYPE_FROM_HANDLE( *iter );
430  if( type != current_type )
431  {
432  if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
433  seq_iter = mMB->sequence_manager()->entity_map( type ).begin();
434  seq_end = mMB->sequence_manager()->entity_map( type ).end();
435  current_type = type;
436  }
437 
438  // Find the sequence containing the current handle
439  while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
440  ++seq_iter;
441  if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
442 
443  // Get the connectivity array
444  EntityHandle* conn_array = NULL;
445  int conn_size = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
446  if( conn_size != vertices_per_elem ) return MB_FAILURE;
447  conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
448 
449  // Determine how much of the sequence we want.
450  Range::pair_iterator pair( iter );
451  Range::const_iterator prev( end );
452  --prev;
453  EntityHandle range_end = pair->second;
454  EntityHandle sequence_end = ( *seq_iter )->end_handle();
455  EntityHandle end_handle = range_end > sequence_end ? sequence_end : range_end;
456  if( end_handle > *prev ) end_handle = *prev;
457  EntityHandle count = end_handle - *iter + 1;
458 
459  // Get offset in sequence to start at
460  assert( *iter >= ( *seq_iter )->start_handle() );
461  EntityHandle offset = *iter - ( *seq_iter )->start_handle();
462 
463  // Make sure sufficient space in output array
464  if( output_iter + ( count * conn_size ) > output_end ) return MB_FAILURE;
465 
466  if( conn_array == NULL )
467  { // If it is structured mesh
468  ErrorCode rval;
469  int temp_buff_size = conn_size * sizeof( EntityHandle );
470  for( unsigned i = 0; i < count; i++ )
471  { // Copy connectivity element by element
472  std::vector< EntityHandle > connect;
473  rval = static_cast< ElementSequence* >( *seq_iter )->get_connectivity( *iter, connect );
474  if( MB_SUCCESS != rval )
475  {
476  return rval;
477  }
478  memcpy( output_iter, &connect[0], temp_buff_size );
479  output_iter += conn_size;
480  ++iter;
481  }
482  }
483  else
484  {
485  // Copy connectivity into output array
486  conn_array += ( conn_size * offset );
487  memcpy( output_iter, conn_array, count * conn_size * sizeof( EntityHandle ) );
488  output_iter += count * conn_size;
489  iter += count;
490  }
491  }
492 
493  return MB_SUCCESS;
494 }
495 
497  const Range::const_iterator& /* end */,
498  int& /* connectivity_size */ )
499 {
500  return MB_NOT_IMPLEMENTED;
501 }
502 
504  const Range::const_iterator& /* end */,
505  const Tag /* node_id_tag */,
506  size_t& /* handle_array_len */,
507  int* const /* handle_array */,
508  size_t& /* index_array_len */,
509  int* const /* index_array */,
510  int& /* index_offset */ )
511 {
512  return MB_NOT_IMPLEMENTED;
513 }
514 
515 ErrorCode WriteUtil::gather_nodes_from_elements( const Range& elements, const Tag node_bit_mark_tag, Range& nodes )
516 {
517  bool printed_warning = false;
518 
519  if( elements.empty() ) return MB_SUCCESS;
520 
521  if( TYPE_FROM_HANDLE( elements.front() ) <= MBVERTEX || TYPE_FROM_HANDLE( elements.back() ) >= MBENTITYSET )
522  return MB_TYPE_OUT_OF_RANGE;
523 
524  // See if we need to use our own marking tag
525  Tag exporting_nodes_tag = 0;
526  if( node_bit_mark_tag )
527  exporting_nodes_tag = node_bit_mark_tag;
528  else
529  {
530  mMB->tag_get_handle( "__MBWriteUtil::exporting_nodes", 1, MB_TYPE_BIT, exporting_nodes_tag, MB_TAG_CREAT );
531  }
532 
533  // The x,y,z tag handles we need
534  EntityHandle lower_bound = ~0, upper_bound = 0;
535 
536  std::vector< EntityHandle > tmp_conn;
537 
539  for( ErrorCode rval = iter.init( elements.begin(), elements.end() ); MB_FAILURE != rval; rval = iter.step() )
540  {
541  if( MB_ENTITY_NOT_FOUND == rval )
542  {
543  if( !printed_warning )
544  {
545  std::cerr << "Warning: ignoring invalid element handle(s) in gather_nodes_from_elements" << std::endl;
546  printed_warning = true;
547  }
548  continue;
549  }
550 
551  ElementSequence* seq = static_cast< ElementSequence* >( iter.get_sequence() );
552 
553  // Get the connectivity array
554  const EntityHandle* conn_array = seq->get_connectivity_array();
555 
556  // If unstructured mesh
557  if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) != MBPOLYHEDRON )
558  {
559  assert( iter.get_start_handle() >= seq->start_handle() );
560  assert( iter.get_end_handle() <= seq->end_handle() );
561  const EntityHandle offset = iter.get_start_handle() - seq->start_handle();
562  const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
563 
564  conn_array += offset * seq->nodes_per_element();
565  const EntityHandle num_node = num_elem * seq->nodes_per_element();
566 
567  // For each node
568  for( EntityHandle j = 0; j < num_node; j++ )
569  {
570  EntityHandle node = conn_array[j];
571  if( node < lower_bound ) lower_bound = node;
572  if( node > upper_bound ) upper_bound = node;
573  unsigned char bit = 0x1;
574  rval = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
575  assert( MB_SUCCESS == rval );
576  if( MB_SUCCESS != rval ) return rval;
577  }
578  }
579  // Polyhedra
580  else if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) == MBPOLYHEDRON )
581  {
582  assert( iter.get_start_handle() >= seq->start_handle() );
583  assert( iter.get_end_handle() <= seq->end_handle() );
584  const EntityHandle offset = iter.get_start_handle() - seq->start_handle();
585  const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
586 
587  conn_array += offset * seq->nodes_per_element();
588  int num_face = num_elem * seq->nodes_per_element();
589 
590  // For each node
591  for( int j = 0; j < num_face; j++ )
592  {
593  const EntityHandle* face_conn = NULL;
594  int face_num_conn = 0;
595  rval = mMB->get_connectivity( conn_array[j], face_conn, face_num_conn, false );
596  if( MB_SUCCESS != rval ) return rval;
597  for( int k = 0; k < face_num_conn; k++ )
598  {
599  EntityHandle node = face_conn[k];
600  if( node < lower_bound ) lower_bound = node;
601  if( node > upper_bound ) upper_bound = node;
602  unsigned char bit = 0x1;
603  rval = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
604  assert( MB_SUCCESS == rval );
605  if( MB_SUCCESS != rval ) return rval;
606  }
607  }
608  }
609  // Structured mesh
610  else
611  {
612  EntityHandle end_h = iter.get_end_handle() + 1;
613  for( EntityHandle h = iter.get_start_handle(); h < end_h; ++h )
614  {
615  tmp_conn.clear();
616  rval = seq->get_connectivity( h, tmp_conn, false );
617  if( MB_SUCCESS != rval )
618  {
619  if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
620  return rval;
621  }
622 
623  // For each node
624  for( size_t j = 0; j < tmp_conn.size(); j++ )
625  {
626  EntityHandle node = tmp_conn[j];
627  if( node < lower_bound ) lower_bound = node;
628  if( node > upper_bound ) upper_bound = node;
629  unsigned char bit = 0x1;
630  mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
631  }
632  }
633  }
634  }
635 
636  // We can get a REALLY long loop if lower_bound is zero
637  assert( lower_bound != 0 );
638  // Gather up all the nodes
639  for( ; upper_bound >= lower_bound; --upper_bound )
640  {
641  unsigned char node_marked = 0;
642  mMB->tag_get_data( exporting_nodes_tag, &upper_bound, 1, &node_marked );
643  if( node_marked == 0x1 ) nodes.insert( upper_bound );
644  }
645 
646  // Clean up our own marking tag
647  if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
648 
649  return MB_SUCCESS;
650 }
651 
652 //! Assign ids to input elements starting with start_id, written to id_tag
653 //! if zero, assigns to GLOBAL_ID_TAG_NAME
654 ErrorCode WriteUtil::assign_ids( Range& elements, Tag id_tag, const int start_id )
655 {
656  ErrorCode result;
657  if( 0 == id_tag )
658  {
659  // Get the global id tag
660  id_tag = mMB->globalId_tag();
661  }
662 
663  // Now assign the ids
664  int i;
665  Range::iterator rit;
666  ErrorCode tmp_result;
667  result = MB_SUCCESS;
668  for( i = start_id, rit = elements.begin(); rit != elements.end(); ++rit, i++ )
669  {
670  tmp_result = mMB->tag_set_data( id_tag, &( *rit ), 1, &i );
671  if( MB_SUCCESS != tmp_result ) result = tmp_result;
672  }
673 
674  return result;
675 }
676 
677 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, Tag id_tag, std::vector< int >& adj )
678 {
679  ErrorCode rval;
680  const EntityHandle* adj_array;
681  int num_adj, id;
682 
683  // Get handles of adjacent entities
684  rval = mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
685  if( MB_SUCCESS != rval )
686  {
687  adj.clear();
688  return rval;
689  }
690 
691  // Append IDs of adjacent entities -- skip meshsets
692  adj.resize( num_adj ); // Pre-allocate space
693  adj.clear(); // Clear used space
694 
695  const EntityHandle* const end = adj_array + num_adj;
696  for( const EntityHandle* iter = adj_array; iter != end; ++iter )
697  {
698  if( TYPE_FROM_HANDLE( *iter ) != MBENTITYSET )
699  {
700  rval = mMB->tag_get_data( id_tag, iter, 1, &id );
701  if( MB_SUCCESS != rval ) return rval;
702  adj.push_back( id );
703  }
704  }
705 
706  return MB_SUCCESS;
707 }
708 
709 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, const EntityHandle*& adj_array, int& num_adj )
710 {
711  return mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
712 }
713 
714 ErrorCode WriteUtil::get_tag_list( std::vector< Tag >& result_list,
715  const Tag* user_tag_list,
716  int user_tag_list_length,
717  bool include_variable_length_tags )
718 {
719  ErrorCode rval;
720 
721  if( user_tag_list )
722  {
723  result_list.clear();
724  result_list.reserve( user_tag_list_length );
725  for( int i = 0; i < user_tag_list_length; ++i )
726  {
727  std::string name;
728  rval = mMB->tag_get_name( user_tag_list[i], name );MB_CHK_SET_ERR( rval, "Error " << (int)rval << " getting name for tag (Invalid input tag handle?)" );
729 
730  if( name.empty() )
731  {
732  MB_SET_ERR( MB_TAG_NOT_FOUND, "Explicit request to save anonymous tag" );
733  }
734 
735  int size;
736  if( !include_variable_length_tags &&
737  MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( user_tag_list[i], size ) )
738  {
739  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "File format cannot store variable-length tag: \"" << name << "\"" );
740  }
741 
742  result_list.push_back( user_tag_list[i] );
743  }
744  }
745  else
746  {
747  std::vector< Tag > temp_list;
748  rval = mMB->tag_get_tags( temp_list );MB_CHK_SET_ERR( rval, "Interface::tag_get_tags failed" );
749 
750  result_list.clear();
751  result_list.reserve( temp_list.size() );
752 
753  std::vector< Tag >::iterator i;
754  for( i = temp_list.begin(); i != temp_list.end(); ++i )
755  {
756  std::string name;
757  rval = mMB->tag_get_name( *i, name );MB_CHK_SET_ERR( rval, "Error " << (int)rval << " getting name for tag (Stale tag handle?)" );
758 
759  // Skip anonymous tags
760  if( name.empty() ) continue;
761 
762  // Skip private/internal tags
763  if( name.size() >= 2 && name[0] == '_' && name[1] == '_' ) continue;
764 
765  // If requested, skip variable-length tags
766  int size;
767  if( !include_variable_length_tags && MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( *i, size ) ) continue;
768 
769  result_list.push_back( *i );
770  }
771  }
772 
773  return MB_SUCCESS;
774 }
775 
778  EntityHandle const** pointers,
779  EntityListType relation,
780  int* lengths,
781  unsigned char* flags )
782 {
784  ErrorCode rval = iter.init( begin, end );
785  while( MB_SUCCESS == rval )
786  {
787  EntityType type = TYPE_FROM_HANDLE( iter.get_start_handle() );
788 
789  if( MBENTITYSET == type )
790  {
791  const MeshSetSequence* seq = reinterpret_cast< MeshSetSequence* >( iter.get_sequence() );
792  const MeshSet* set;
793  int len = 0;
794  size_t clen;
795  for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
796  {
797  set = seq->get_set( h );
798  switch( relation )
799  {
800  case CONTENTS:
801  *pointers = set->get_contents( clen );
802  len = clen;
803  break;
804  case CHILDREN:
805  *pointers = set->get_children( len );
806  break;
807  case PARENTS:
808  *pointers = set->get_parents( len );
809  break;
810  }
811  if( lengths )
812  {
813  *lengths = len;
814  ++lengths;
815  }
816  if( flags )
817  {
818  *flags = (unsigned char)set->flags();
819  ++flags;
820  }
821  ++pointers;
822  }
823  }
824 
825  else if( MBVERTEX != type )
826  {
827  const bool topological = ( relation == TOPOLOGICAL );
828  int len;
829  const ElementSequence* seq = reinterpret_cast< ElementSequence* >( iter.get_sequence() );
830  for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
831  {
832  rval = seq->get_connectivity( h, *pointers, len, topological );
833  if( MB_SUCCESS != rval ) return rval;
834  if( lengths )
835  {
836  *lengths = len;
837  ++lengths;
838  }
839  if( flags )
840  {
841  *flags = 0;
842  ++flags;
843  }
844  ++pointers;
845  }
846  }
847  else
848  {
849  return MB_TYPE_OUT_OF_RANGE;
850  }
851 
852  rval = iter.step();
853  }
854  if( MB_FAILURE == rval )
855  return MB_SUCCESS; // At end of list
856  else
857  return rval;
858 }
859 
861  int num_entities,
862  EntityHandle const** pointers,
863  EntityListType relation,
864  int* lengths,
865  unsigned char* flags )
866 {
868  const EntitySequence* tmp_seq;
869  ErrorCode rval = MB_SUCCESS;
870  for( int i = 0; i < num_entities; i++ )
871  {
872  rval = sm->find( entities[i], tmp_seq );
873  if( MB_SUCCESS != rval ) return rval;
874 
875  EntityType type = TYPE_FROM_HANDLE( entities[i] );
876 
877  if( MBENTITYSET == type )
878  {
879  const MeshSetSequence* seq = reinterpret_cast< const MeshSetSequence* >( tmp_seq );
880  const MeshSet* set;
881  int len = 0;
882  size_t clen;
883  set = seq->get_set( entities[i] );
884  switch( relation )
885  {
886  case CONTENTS:
887  *pointers = set->get_contents( clen );
888  len = clen;
889  break;
890  case CHILDREN:
891  *pointers = set->get_children( len );
892  break;
893  case PARENTS:
894  *pointers = set->get_parents( len );
895  break;
896  }
897  if( lengths )
898  {
899  *lengths = len;
900  ++lengths;
901  }
902  if( flags )
903  {
904  *flags = (unsigned char)set->flags();
905  ++flags;
906  }
907  ++pointers;
908  }
909  else if( MBVERTEX != type )
910  {
911  const bool topological = ( relation == TOPOLOGICAL );
912  int len;
913  const ElementSequence* seq = reinterpret_cast< const ElementSequence* >( tmp_seq );
914  rval = seq->get_connectivity( entities[i], *pointers, len, topological );
915  if( MB_SUCCESS != rval ) return rval;
916  if( lengths )
917  {
918  *lengths = len;
919  ++lengths;
920  }
921  if( flags )
922  {
923  *flags = 0;
924  ++flags;
925  }
926  ++pointers;
927  }
928  else
929  {
930  return MB_TYPE_OUT_OF_RANGE;
931  }
932  }
933 
934  return MB_SUCCESS;
935 }
936 
937 } // namespace moab