Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
ReadRTT.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 Coroporation, 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 /**
17  * \class ReadRTT
18  * \brief ReadRTT based on ReadNASTRAN
19  *
20  * See:
21  *
22  * \author Andrew Davis
23  */
24 
25 #include "ReadRTT.hpp"
26 
27 #include <cassert>
28 #include <cmath>
29 #include <cstdlib>
30 #include <fstream>
31 #include <iostream>
32 #include <map>
33 #include <sstream>
34 #include <vector>
35 
36 #include "FileTokenizer.hpp"
37 #include "Internals.hpp" // for MB_START_ID
38 #include "MBTagConventions.hpp"
39 #include "moab/CN.hpp"
40 #include "moab/ErrorHandler.hpp"
41 #include "moab/FileOptions.hpp"
42 #include "moab/GeomTopoTool.hpp"
43 #include "moab/Interface.hpp"
44 #include "moab/Range.hpp"
45 #include "moab/ReadUtilIface.hpp"
46 #include "moab/Skinner.hpp"
47 
48 namespace moab
49 {
50 
52 {
53  return new ReadRTT( iface );
54 }
55 
56 // constructor
58  : MBI( impl ), geom_tag( 0 ), id_tag( 0 ), name_tag( 0 ), category_tag( 0 ), faceting_tol_tag( 0 )
59 {
60  assert( NULL != impl );
61  myGeomTool = new GeomTopoTool( impl );
63  assert( NULL != readMeshIface );
64 
65  // this section copied from ReadCGM initalisation
66  int negone = -1;
67  double zero = 0.;
68  ErrorCode rval;
70  &negone );
71  MB_CHK_ERR_CONT( rval );
72  id_tag = MBI->globalId_tag();
74  MB_CHK_ERR_CONT( rval );
77  MB_CHK_ERR_CONT( rval );
78  rval =
80  MB_CHK_ERR_CONT( rval );
81 }
82 
83 // destructor
85 {
86  if( readMeshIface )
87  {
89  readMeshIface = 0;
90  }
91 
92  delete myGeomTool;
93 }
94 
95 ErrorCode ReadRTT::read_tag_values( const char* /*file_name*/,
96  const char* /*tag_name*/,
97  const FileOptions& /*opts*/,
98  std::vector< int >& /*tag_values_out*/,
99  const SubsetList* /*subset_list*/ )
100 {
101  return MB_NOT_IMPLEMENTED;
102 }
103 
104 // load the file as called by the Interface function
105 ErrorCode ReadRTT::load_file( const char* filename,
106  const EntityHandle*,
107  const FileOptions&,
108  const ReaderIface::SubsetList* subset_list,
109  const Tag* /*file_id_tag*/ )
110 {
111  ErrorCode rval;
112 
113  // at this time there is no support for reading a subset of the file
114  if( subset_list )
115  {
116  std::cout << "Subset reading not supported for RTT meshes" << std::endl;
118  }
119 
120  // test to see if file exists
121  FILE* file = NULL;
122  file = fopen( filename, "r" );
123  if( file == NULL ) return MB_FILE_DOES_NOT_EXIST;
124  // otherwise close the file
125  fclose( file );
126 
127  // read the header
128  rval = ReadRTT::read_header( filename );
129  if( rval != MB_SUCCESS ) return rval;
130 
131  // read the side_flag data
132  rval = ReadRTT::read_side_flags( filename );
133  if( rval != MB_SUCCESS ) return rval;
134 
135  // read the cell data
136  rtt_flags cell_flags;
137  rval = ReadRTT::read_cell_flags( filename );
138  if( rval != MB_SUCCESS ) return rval;
139 
140  // read the node data
141  std::vector< node > node_data;
142  rval = ReadRTT::read_nodes( filename, node_data );
143  if( rval != MB_SUCCESS ) return rval;
144 
145  // read the facet data
146  std::vector< facet > facet_data;
147  rval = ReadRTT::read_facets( filename, facet_data );
148  if( rval != MB_SUCCESS ) return rval;
149 
150  // read the tetrahedra data
151  std::vector< tet > tet_data;
152  rval = ReadRTT::read_tets( filename, tet_data );
153  if( rval != MB_SUCCESS ) return rval;
154 
155  // make the map of surface number in the rttmesh to the surface meshset
156  std::map< int, EntityHandle > surface_map; // corrsespondance of surface number to entity handle
157  std::map< int, EntityHandle > volume_map; // corrsespondance of volume number to entity handle
158  rval = ReadRTT::generate_topology( side_data, cell_data, tet_data, surface_map, volume_map );
159  if( rval != MB_SUCCESS ) return rval;
160 
161  // generate the rest of the database, triangles to surface meshsets etc
162  rval = ReadRTT::build_moab( node_data, facet_data, tet_data, surface_map, volume_map );
163  if( rval != MB_SUCCESS ) return rval;
164 
165  return MB_SUCCESS;
166 }
167 
168 /*
169  * builds the topology of the problem
170  */
171 ErrorCode ReadRTT::generate_topology( std::vector< side > side_data,
172  std::vector< cell > cell_data,
173  std::vector< tet > tet_data,
174  std::map< int, EntityHandle >& surface_map,
175  std::map< int, EntityHandle >& volume_map )
176 {
177 
178  ErrorCode rval;
179  std::vector< EntityHandle > entmap[4];
180  int num_ents[4]; // number of entities in each dimension
181 
182  const char geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0", "Group\0" };
183 
184  std::vector< int > surface_numbers; // the surface numbers in the problem
185 
186  // corresponds to number of cad like surfaces and cad like volumes
187  num_ents[2] = side_data.size();
188  num_ents[3] = cell_data.size();
189 
190  // loop over surfaces & volumes
191  for( int dim = 2; dim <= 3; dim++ )
192  {
193  for( int i = 0; i != num_ents[dim]; i++ )
194  {
195  EntityHandle handle;
196  // create a meshset for each entity surface/volume
197  rval = MBI->create_meshset( dim == 1 ? MESHSET_ORDERED : MESHSET_SET, handle );
198  // if failure
199  if( rval != MB_SUCCESS ) return rval;
200 
201  // collect the entity handles into an
202  entmap[dim].push_back( handle );
203 
204  // set the dimension tag
205  rval = MBI->tag_set_data( geom_tag, &handle, 1, &dim );
206  // if fail
207  if( MB_SUCCESS != rval ) return rval;
208  // if we are a surface
209  if( dim == 2 )
210  {
211  // tag the id onto the surface meshset
212  rval = MBI->tag_set_data( id_tag, &handle, 1, &side_data[i].id );
213  // inesert entity into the map
214  surface_map[side_data[i].id] = handle;
215  }
216  else
217  {
218  // otherwise we set the volume tag data, loop is only 2 & 3 dim
219  rval = MBI->tag_set_data( id_tag, &handle, 1, &cell_data[i].id );
220  volume_map[cell_data[i].id] = handle;
221  }
222  // if fail
223  if( MB_SUCCESS != rval ) return rval;
224  // set the category tag
225  rval = MBI->tag_set_data( category_tag, &handle, 1, &geom_categories[dim] );
226  if( MB_SUCCESS != rval ) return rval;
227  }
228  }
229 
230  // generate parent child links
231  // best to loop over the surfaces and assign them to volumes, we can then
232  // assign facets to
233  // to each surface
234  generate_parent_child_links( num_ents, entmap, side_data, cell_data );
235 
236  // set the surface senses
237  set_surface_senses( num_ents, entmap, side_data, cell_data );
238 
239  // set the group data
240  MB_CHK_ERR(setup_group_data( entmap, tet_data, volume_map ));
241 
242  return MB_SUCCESS;
243 }
244 
245 /*
246  * builds the moab representation of the mesh
247  */
248 ErrorCode ReadRTT::build_moab( std::vector< node > node_data,
249  std::vector< facet > facet_data,
250  std::vector< tet > tet_data,
251  const std::map< int, EntityHandle > surface_map,
252  const std::map< int, EntityHandle > volume_map )
253 {
254  ErrorCode rval;
255  EntityHandle file_set;
256 
257  rval = MBI->create_meshset( MESHSET_SET, file_set );
258  if( MB_SUCCESS != rval ) return rval;
259 
260  // adding vertex set to the file set
261  Range mb_coords;
262  for( const auto& n : node_data )
263  {
264  double coords[3] = { n.x, n.y, n.z };
265  EntityHandle v;
266  MB_CHK_ERR( MBI->create_vertex( coords, v ) );
267  mb_coords.insert( v );
268  }
269  MB_CHK_ERR( MBI->add_entities( file_set, mb_coords ) );
270 
271  // add facets to the file set
272  MB_CHK_ERR( create_facets( facet_data, surface_map, mb_coords, file_set ) );
273 
274  // adding material groups
275  std::string mat_flag = get_material_ref_flag();
276  std::string vol_flag = get_volume_ref_flag();
277 
278  // Only create the material number tag if a MATERIAL flag exists in the file
279  Tag mat_num_tag = 0;
280  bool have_material_flag = !mat_flag.empty() && cell_flag_idx.find( mat_flag ) != cell_flag_idx.end();
281  if( have_material_flag )
282  {
283  MB_CHK_ERR(
284  MBI->tag_get_handle( "MATERIAL_NUMBER", 1, MB_TYPE_INTEGER, mat_num_tag, MB_TAG_SPARSE | MB_TAG_CREAT ) );
285  }
286 
287  // add tets to the file set
288  Range mb_tets;
289  for( const auto& t : tet_data )
290  {
291  EntityHandle tet_nodes[4] = { mb_coords[t.connectivity[0] - 1], mb_coords[t.connectivity[1] - 1],
292  mb_coords[t.connectivity[2] - 1], mb_coords[t.connectivity[3] - 1] };
293 
294  EntityHandle tet_h;
295  MB_CHK_ERR( MBI->create_element( MBTET, tet_nodes, 4, tet_h ) );
296 
297  // Tag material number only when a MATERIAL flag is present in the file
298  if( have_material_flag )
299  {
300  int mat_no = t.flag_values[cell_flag_idx[mat_flag]];
301  MB_CHK_ERR( MBI->tag_set_data( mat_num_tag, &tet_h, 1, &mat_no ) );
302  }
303 
304  int volume_no = t.flag_values[cell_flag_idx[vol_flag]];
305  if( volume_map.find( volume_no ) != volume_map.end() )
306  {
307  EntityHandle vol_set = volume_map.at( volume_no );
308  rval = MBI->add_entities( vol_set, &tet_h, 1 );MB_CHK_ERR( rval );
309  }
310  else
311  {
312  std::cout << "Warning: volume number " << volume_no << " not found in volume map" << std::endl;
313  }
314 
315  mb_tets.insert( tet_h );
316  }
317  MB_CHK_ERR( MBI->add_entities( file_set, mb_tets ) );
318 
319  // For discontiguous meshes with no side/facet data, generate surfaces by
320  // skinning each volume's tetrahedra. This produces the boundary triangles
321  // needed by DAGMC for ray tracing.
322  if( header_data.contiguity == "discontiguous" && facet_data.empty() )
323  {
324  const char surf_category[CATEGORY_TAG_SIZE] = "Surface\0";
325  int surf_dim = 2;
326  int surf_id = 1;
327  Skinner skinner( MBI );
328 
329  for( auto it = volume_map.begin(); it != volume_map.end(); ++it )
330  {
331  EntityHandle vol_set = it->second;
332 
333  // Get all tets in this volume
334  Range vol_tets;
335  MB_CHK_ERR( MBI->get_entities_by_type( vol_set, MBTET, vol_tets ) );
336  if( vol_tets.empty() ) continue;
337 
338  // Skin the tets to get boundary triangles
340  rval = skinner.find_skin( 0, vol_tets, false, skin_tris, 0, true, true );
341  MB_CHK_ERR( rval );
342 
343  // Get the vertices referenced by the skin triangles
344  Range skin_verts;
345  MB_CHK_ERR( MBI->get_connectivity( skin_tris, skin_verts ) );
346 
347  // Create a surface meshset
348  EntityHandle surf_handle;
349  MB_CHK_ERR( MBI->create_meshset( MESHSET_SET, surf_handle ) );
350  MB_CHK_ERR( MBI->tag_set_data( geom_tag, &surf_handle, 1, &surf_dim ) );
351  MB_CHK_ERR( MBI->tag_set_data( id_tag, &surf_handle, 1, &surf_id ) );
352  MB_CHK_ERR( MBI->tag_set_data( category_tag, &surf_handle, 1, surf_category ) );
353 
354  // Add skin triangles and vertices to the surface meshset
355  MB_CHK_ERR( MBI->add_entities( surf_handle, skin_tris ) );
356  MB_CHK_ERR( MBI->add_entities( surf_handle, skin_verts ) );
357 
358  // Also add the skin triangles to the file set
359  MB_CHK_ERR( MBI->add_entities( file_set, skin_tris ) );
360 
361  // Set volume -> surface parent-child link
362  MB_CHK_ERR( MBI->add_parent_child( vol_set, surf_handle ) );
363 
364  // Set surface sense: forward with respect to this volume
365  MB_CHK_ERR( myGeomTool->set_sense( surf_handle, vol_set, SENSE_FORWARD ) );
366 
367  surf_id++;
368  }
369  }
370 
371  return MB_SUCCESS;
372 }
373 
374 // Function to create a material group
375 ErrorCode ReadRTT::create_material_group( const std::string& material_name, int material_id, EntityHandle& handle )
376 {
377  ErrorCode rval = MBI->create_meshset( MESHSET_SET, handle );
378  if( rval != MB_SUCCESS ) return rval;
379 
380  // NAME
381  char name_val[NAME_TAG_SIZE] = { 0 };
382  std::strncpy( name_val, material_name.c_str(), NAME_TAG_SIZE - 1 );
383  MB_CHK_ERR( MBI->tag_set_data( name_tag, &handle, 1, name_val ) );
384 
385  // GLOBAL_ID
386  MB_CHK_ERR( MBI->tag_set_data( id_tag, &handle, 1, &material_id ) );
387 
388  // CATEGORY
389  char cat[CATEGORY_TAG_SIZE] = { 0 };
390  std::strncpy( cat, "Group", CATEGORY_TAG_SIZE - 1 );
391  MB_CHK_ERR( MBI->tag_set_data( category_tag, &handle, 1, cat ) );
392 
393  // GEOM_DIMENSION = 4
394  int dim4 = 4;
395  MB_CHK_ERR( MBI->tag_set_data( geom_tag, &handle, 1, &dim4 ) );
396 
397  return MB_SUCCESS;
398 }
399 
400 ErrorCode ReadRTT::create_facets( const std::vector< facet >& facet_data,
401  const std::map< int, EntityHandle >& surface_map,
402  Range& mb_coords,
403  EntityHandle file_set )
404 {
405  Tag side_id_tag, surface_number_tag;
406  // Obtain or create tags for side IDs and surface numbers
407  MB_CHK_ERR( MBI->tag_get_handle( "SIDEID_TAG", 1, MB_TYPE_INTEGER, side_id_tag, MB_TAG_SPARSE | MB_TAG_CREAT ) );
408  MB_CHK_ERR(
409  MBI->tag_get_handle( "SURFACE_NUMBER", 1, MB_TYPE_INTEGER, surface_number_tag, MB_TAG_SPARSE | MB_TAG_CREAT ) );
410 
411  EntityHandle triangle;
412  Range mb_tris; // For storing triangles
413 
414  for( const auto& tmp : facet_data )
415  {
416  EntityHandle tri_nodes[3] = { mb_coords[tmp.connectivity[0] - 1], mb_coords[tmp.connectivity[1] - 1],
417  mb_coords[tmp.connectivity[2] - 1] };
418  MB_CHK_ERR( MBI->create_element( MBTRI, tri_nodes, 3, triangle ) );
419  // tag in side id on the triangle
420  MB_CHK_ERR( MBI->tag_set_data( side_id_tag, &triangle, 1, &tmp.side_id ) );
421  // tag the surface number on the triangle
422  MB_CHK_ERR( MBI->tag_set_data( surface_number_tag, &triangle, 1, &tmp.surface_number ) );
423  // insert vertices and triangles into the appropriate surface meshset
424  EntityHandle meshset_handle = surface_map.at( tmp.surface_number );
425  // also set surface tag
426  MB_CHK_ERR( MBI->tag_set_data( side_id_tag, &meshset_handle, 1, &tmp.side_id ) );
427  MB_CHK_ERR( MBI->tag_set_data( surface_number_tag, &meshset_handle, 1, &tmp.surface_number ) );
428  // add vertices to the mesh
429  MB_CHK_ERR( MBI->add_entities( meshset_handle, tri_nodes, 3 ) );
430  // add triangles to the meshset
431  MB_CHK_ERR( MBI->add_entities( meshset_handle, &triangle, 1 ) );
432  // insert triangles into mb_tris
433  mb_tris.insert( triangle );
434  }
435  MB_CHK_ERR( MBI->add_entities( file_set, mb_tris ) );
436 
437  return MB_SUCCESS;
438 }
439 
441 {
442  // Create CONTIGUITY tag and set its value
443  Tag contiguity_tag;
444  const char* contiguity_value = header_data.contiguity.c_str();
445  MB_CHK_ERR( MBI->tag_get_handle( "CONTIGUITY", strlen( contiguity_value ) + 1, MB_TYPE_OPAQUE, contiguity_tag,
447  MB_CHK_ERR( MBI->tag_set_data( contiguity_tag, &file_set, 1, contiguity_value ) );
448 
449  return moab::MB_SUCCESS;
450 }
451 
452 /*
453  * read the header data from the filename pointed to
454  */
455 ErrorCode ReadRTT::read_header( const char* filename )
456 {
457  std::ifstream input_file( filename ); // filename for rtt file
458  // file ok?
459  if( !input_file.good() )
460  {
461  std::cout << "Problems reading file = " << filename << std::endl;
462  return MB_FAILURE;
463  }
464 
465  // if it works
466  std::string line;
467  moab::ErrorCode rval = MB_FAILURE;
468  if( input_file.is_open() )
469  {
470  while( std::getline( input_file, line ) )
471  {
472  if( line.compare( "header" ) == 0 )
473  {
474  rval = get_header_data( input_file );
475  }
476  else if( line.compare( "dims" ) == 0 )
477  {
478  rval = parse_dims( input_file );
479  }
480  else if( line.compare( "cell_defs" ) == 0 )
481  {
483  }
484  }
485  input_file.close();
486  }
487  return rval;
488 }
489 
490 // read all flags from a section
491 ErrorCode ReadRTT::read_all_flags( const char* filename,
492  std::vector< int > n_flags,
493  std::string flag_id,
494  rtt_flags& flags,
495  std::map< std::string, int >& flag_idx )
496 {
497  std::string start_flag = flag_id + "_flags";
498  std::string end_flag = "end_" + start_flag + "\0";
499  std::string line; // the current line being read
500  std::ifstream input_file( filename ); // filestream for rttfile
501  std::vector< std::string > flag_order; // order of the flags
502  // file ok?
503  if( !input_file.good() )
504  {
505  std::cout << "Problems reading file = " << filename << std::endl;
506  return MB_FAILURE;
507  }
508  // if it works
509  if( input_file.is_open() )
510  {
511  while( std::getline( input_file, line ) )
512  {
513  if( line.compare( start_flag ) == 0 )
514  {
515  while( std::getline( input_file, line ) )
516  {
517  // Read all the side block until we find the end
518  if( line.compare( end_flag ) == 0 ) break;
519  std::vector< std::string > token = ReadRTT::split_string( line, ' ' );
520  if( token.size() != 2 )
521  {
522  std::cout << "Error reading side flags" << std::endl;
523  return MB_FAILURE;
524  }
525  int flag_key = std::stoi( token[0] ) - 1;
526  std::string key = token[1];
527  flag_order.push_back( key );
528  for( int i = 0; i < n_flags[flag_key]; i++ )
529  {
530  std::getline( input_file, line );
531  flags[key].push_back( line );
532  }
533  }
534  }
535  }
536  input_file.close();
537  }
538  for( size_t i = 0; i < flag_order.size(); i++ )
539  {
540  std::string key = flag_order[i];
541  // fill the index
542  flag_idx[key] = i;
543  }
544  return MB_SUCCESS;
545 }
546 
547 /*
548  * reads the side data from the filename pointed to
549  */
550 ErrorCode ReadRTT::read_side_flags( const char* filename )
551 {
552  rtt_flags side_flags;
553 
554  ErrorCode rval = MB_FAILURE;
555  // read all the side data
556  rval = read_all_flags( filename, dim_data.nside_flags, "side", side_flags, side_flag_idx );
557 
558  //process sides
559  rval = ReadRTT::side_process_faces( side_flags, side_data );
560  if( rval != MB_SUCCESS ) return rval;
561 
562  return rval;
563 }
564 
565 /*
566  * process the FACES flag from the side_flags section
567  */
568 ErrorCode ReadRTT::side_process_faces( rtt_flags side_flags, std::vector< side >& side_data )
569 {
570  if( side_flags.find( "FACES" ) != side_flags.end() )
571  {
572  for( size_t i = 0; i < side_flags["FACES"].size(); i++ )
573  {
574  side data = ReadRTT::get_side_data( side_flags["FACES"][i] );
575  side_data.push_back( data );
576  }
577  }
578  if( side_data.size() == 0 && header_data.contiguity != "discontiguous" ) return MB_FAILURE;
579  return MB_SUCCESS;
580 }
581 
583 {
584  std::string material_ref_flag = ""; // set defaul to REGIONS
585  if( cell_flag_datas.find( "MATERIAL" ) != cell_flag_datas.end() )
586  {
587  material_ref_flag = "MATERIAL";
588  }
589  return material_ref_flag;
590 }
591 
593 {
594  std::string part_ref_flag = "REGIONS"; // set defaul to REGIONS
595  if( cell_flag_datas.find( "MCNP_PSEUDO-CELLS" ) != cell_flag_datas.end() )
596  {
597  part_ref_flag = "MCNP_PSEUDO-CELLS";
598  }
599  else if( cell_flag_datas.find( "ABAQUS_PARTS" ) != cell_flag_datas.end() )
600  {
601  part_ref_flag = "ABAQUS_PARTS";
602  }
603  return part_ref_flag;
604 }
605 
606 /*
607  * reads the cell data from the filename pointed to
608  */
609 ErrorCode ReadRTT::read_cell_flags( const char* filename )
610 {
611  rtt_flags cell_flags;
612  ErrorCode rval = MB_FAILURE;
613  // read all the cell data
614  rval = read_all_flags( filename, dim_data.ncell_flags, "cell", cell_flags, cell_flag_idx );
615 
616  for( auto it = cell_flags.begin(); it != cell_flags.end(); ++it )
617  {
618  std::string key = it->first;
619  // fill the index
620  rval = ReadRTT::cell_process_flag( cell_flags, key );
621  if( rval != MB_SUCCESS ) return rval;
622  }
623 
624  std::string part_flag_name = get_volume_ref_flag();
625  cell_data = cell_flag_datas[part_flag_name];
626  cell_data_idx = cell_flag_indexes[part_flag_name];
627  return rval;
628 }
629 
630 /*
631  * process the standard flag from the cell_flags section
632  */
633 ErrorCode ReadRTT::cell_process_flag( rtt_flags cell_flags, std::string key )
634 {
635  std::vector< cell > cell_data;
636  // check if the key is in the cell_flags
637  if( cell_flags.find( key ) != cell_flags.end() )
638  {
639  for( size_t i = 0; i < cell_flags[key].size(); i++ )
640  {
641  cell data = ReadRTT::get_cell_data( cell_flags[key][i] );
642  cell_data.push_back( data );
643  }
644  if( cell_data.size() == 0 ) return MB_FAILURE;
645  }
646 
647  // fill the corresponding index
648  std::map< int, int > cell_data_idx;
649  for( size_t i = 0; i < cell_data.size(); ++i )
650  {
651  cell tmp = cell_data[i];
652  cell_data_idx[tmp.id] = i;
653  }
654  if( cell_data.size() > 0 ) cell_flag_datas[key] = cell_data;
656 
657  return MB_SUCCESS;
658 }
659 
660 /*
661  * Reads the node data fromt the filename pointed to
662  */
663 ErrorCode ReadRTT::read_nodes( const char* filename, std::vector< node >& node_data )
664 {
665  std::string line; // the current line being read
666  std::ifstream input_file( filename ); // filestream for rttfile
667  // file ok?
668  if( !input_file.good() )
669  {
670  std::cout << "Problems reading file = " << filename << std::endl;
671  return MB_FAILURE;
672  }
673 
674  // if it works
675  if( input_file.is_open() )
676  {
677  while( std::getline( input_file, line ) )
678  {
679  if( line.compare( "nodes\0" ) == 0 )
680  {
681  // read lines until find end nodes
682  while( std::getline( input_file, line ) )
683  {
684  if( line.compare( "end_nodes\0" ) == 0 ) break;
685  node data = ReadRTT::get_node_data( line );
686  node_data.push_back( data );
687  }
688  }
689  }
690  input_file.close();
691  }
692  if( node_data.size() == 0 ) return MB_FAILURE;
693  return MB_SUCCESS;
694 }
695 
696 /*
697  * Reads the facet data fromt the filename pointed to
698  */
699 ErrorCode ReadRTT::read_facets( const char* filename, std::vector< facet >& facet_data )
700 {
701  std::string line; // the current line being read
702  std::ifstream input_file( filename ); // filestream for rttfile
703  // file ok?
704  if( !input_file.good() )
705  {
706  std::cout << "Problems reading file = " << filename << std::endl;
707  return MB_FAILURE;
708  }
709 
710  // if it works
711  if( input_file.is_open() )
712  {
713  while( std::getline( input_file, line ) )
714  {
715  if( line.compare( "sides\0" ) == 0 )
716  {
717  // read lines until find end nodes
718  while( std::getline( input_file, line ) )
719  {
720  if( line.compare( "end_sides\0" ) == 0 ) break;
721  facet data = ReadRTT::get_facet_data( line );
722  facet_data.push_back( data );
723  }
724  }
725  }
726  input_file.close();
727  }
728  if( facet_data.size() == 0 && header_data.contiguity != "discontiguous" ) return MB_FAILURE;
729  return MB_SUCCESS;
730 }
731 
732 /*
733  * Reads the facet data fromt the filename pointed to
734  */
735 ErrorCode ReadRTT::read_tets( const char* filename, std::vector< tet >& tet_data )
736 {
737  std::string line; // the current line being read
738  std::ifstream input_file( filename ); // filestream for rttfile
739  // file ok?
740  if( !input_file.good() )
741  {
742  std::cout << "Problems reading file = " << filename << std::endl;
743  return MB_FAILURE;
744  }
745  // if it works
746  if( input_file.is_open() )
747  {
748  while( std::getline( input_file, line ) )
749  {
750  if( line.compare( "cells\0" ) == 0 )
751  {
752  // read lines until find end nodes
753  while( std::getline( input_file, line ) )
754  {
755  if( line.compare( "end_cells\0" ) == 0 ) break;
756  tet data = ReadRTT::get_tet_data( line );
757  tet_data.push_back( data );
758  }
759  }
760  }
761  input_file.close();
762  }
763  if( tet_data.size() == 0 ) return MB_FAILURE;
764  return MB_SUCCESS;
765 }
766 
767 /*
768  * given the open file handle read until we find
769  */
771 {
772  std::string line;
773  while( std::getline( input_file, line ) )
774  {
775 
776  // tokenize the line
777  std::istringstream iss( line );
778  std::vector< std::string > split_string;
779  do
780  {
781  std::string sub_string;
782  iss >> sub_string;
783  split_string.push_back( sub_string );
784  } while( iss );
785 
786  // if we find version
787  if( line.find( "version" ) != std::string::npos )
788  {
789  if( split_string[1].find( "v" ) != std::string::npos &&
790  split_string[0].find( "version" ) != std::string::npos )
791  {
793  }
794  }
795  else if( line.find( "title" ) != std::string::npos )
796  {
798  }
799  else if( line.find( "date" ) != std::string::npos )
800  {
802  }
803  else if( line.find( "contiguity" ) != std::string::npos )
804  {
806  }
807  else if( line.find( "end_header" ) != std::string::npos )
808  {
809  return MB_SUCCESS;
810  }
811  }
812  // otherwise we never found the end_header keyword
813  return MB_FAILURE;
814 }
815 
817 {
818  if( !input_file.good() || !input_file.is_open() )
819  {
820  std::cout << "Problems reading file" << std::endl;
821  return MB_FAILURE;
822  }
823 
824  // Track header values that are not stored but should be consistent with a tet mesh.
825  // -1 indicates the field was not present in the file.
826  int nnodes_side_max_val = -1;
827  int ndim_topo_val = -1;
828 
829  std::string line;
830  std::vector< std::string > tokens;
831  while( std::getline( input_file, line ) )
832  {
833  if( line == "" ) continue;
834  if( line.find( "end_dims" ) != std::string::npos ) break;
835 
836  tokens = ReadRTT::split_string( line, ' ' );
837  if( tokens[0] == "coor_units" )
838  {
839  dim_data.coor_units = tokens[1];
840  }
841  else if( tokens[0] == "prob_time_units" )
842  {
843  dim_data.prob_time_units = tokens[1];
844  }
845  else if( tokens[0] == "ncell_defs" )
846  {
847  dim_data.ncell_defs = std::atoi( tokens[1].c_str() );
848  }
849  else if( tokens[0] == "nnodes_max" )
850  {
851  dim_data.nnodes_max = std::atoi( tokens[1].c_str() );
852  }
853  else if( tokens[0] == "nsides_max" )
854  {
855  dim_data.nsides_max = std::atoi( tokens[1].c_str() );
856  }
857  else if( tokens[0] == "nnodes_side_max" )
858  {
859  nnodes_side_max_val = std::atoi( tokens[1].c_str() );
860  }
861  else if( tokens[0] == "ndim_topo" )
862  {
863  ndim_topo_val = std::atoi( tokens[1].c_str() );
864  }
865  else if( tokens[0] == "ndim" )
866  {
867  dim_data.ndim = std::atoi( tokens[1].c_str() );
868  }
869  else if( tokens[0] == "nnodes" )
870  {
871  dim_data.nnodes = std::atoi( tokens[1].c_str() );
872  }
873  else if( tokens[0] == "nnode_flag_types" )
874  {
875  dim_data.nnode_flag_types = std::atoi( tokens[1].c_str() );
876  }
877  else if( tokens[0] == "nnode_flags" )
878  {
879  for( size_t i = 1; i < tokens.size(); i++ )
880  {
881  dim_data.nnode_flags.push_back( std::atoi( tokens[i].c_str() ) );
882  }
883  }
884  else if( tokens[0] == "nnode_data" )
885  {
886  dim_data.nnode_data = std::atoi( tokens[1].c_str() );
887  }
888  else if( tokens[0] == "nsides" )
889  {
890  dim_data.nsides = std::atoi( tokens[1].c_str() );
891  }
892  else if( tokens[0] == "nside_types" )
893  {
894  dim_data.nside_types = std::atoi( tokens[1].c_str() );
895  }
896  else if( tokens[0] == "side_types" )
897  {
898  dim_data.side_types = std::atoi( tokens[1].c_str() );
899  }
900  else if( tokens[0] == "nside_flag_types" )
901  {
902  dim_data.nside_flag_types = std::atoi( tokens[1].c_str() );
903  }
904  else if( tokens[0] == "nside_flags" )
905  {
906  for( size_t i = 1; i < tokens.size(); i++ )
907  {
908  dim_data.nside_flags.push_back( std::atoi( tokens[i].c_str() ) );
909  }
910  }
911  else if( tokens[0] == "nside_data" )
912  {
913  dim_data.nside_data = std::atoi( tokens[1].c_str() );
914  }
915  else if( tokens[0] == "ncells" )
916  {
917  dim_data.ncells = std::atoi( tokens[1].c_str() );
918  }
919  else if( tokens[0] == "ncell_types" )
920  {
921  dim_data.ncell_types = std::atoi( tokens[1].c_str() );
922  }
923  else if( tokens[0] == "cell_types" )
924  {
925  dim_data.cell_types = std::atoi( tokens[1].c_str() );
926  }
927  else if( tokens[0] == "ncell_flag_types" )
928  {
929  dim_data.ncell_flag_types = std::atoi( tokens[1].c_str() );
930  }
931  else if( tokens[0] == "ncell_flags" )
932  {
933  for( size_t i = 1; i < tokens.size(); i++ )
934  {
935  dim_data.ncell_flags.push_back( std::atoi( tokens[i].c_str() ) );
936  }
937  }
938  else if( tokens[0] == "ncell_data" )
939  {
940  dim_data.ncell_data = std::atoi( tokens[1].c_str() );
941  }
942  }
943  // Warn if nnodes_side_max or ndim_topo are missing or inconsistent with a tet mesh.
944  // The reader assumes triangle sides (3 nodes per side) and 3D topology throughout.
945  if( nnodes_side_max_val == -1 )
946  std::cerr << "Warning: nnodes_side_max not found in dims block; expected 3 for a tet mesh." << std::endl;
947  else if( nnodes_side_max_val != 3 )
948  std::cerr << "Warning: nnodes_side_max is " << nnodes_side_max_val
949  << "; expected 3 for a tet mesh. Results may be incorrect." << std::endl;
950 
951  if( ndim_topo_val == -1 )
952  std::cerr << "Warning: ndim_topo not found in dims block; expected 3 for a tet mesh." << std::endl;
953  else if( ndim_topo_val != 3 )
954  std::cerr << "Warning: ndim_topo is " << ndim_topo_val
955  << "; expected 3 for a tet mesh. Results may be incorrect." << std::endl;
956 
957  // Check that the data is valid and has the expected number of entries
958  dim_data.validate();
959 
960  return MB_SUCCESS;
961 }
962 
963 /*
964  * parsing the cell deifinitions
965  */
967 {
968  if( !input_file.good() || !input_file.is_open() )
969  {
970  std::cout << "Problems reading file" << std::endl;
971  return MB_FAILURE;
972  }
973 
974  std::string line;
975  std::vector< std::string > tokens;
976  while( std::getline( input_file, line ) )
977  {
978  if( line == "" ) continue;
979  if( line.find( "end_cell_defs" ) != std::string::npos ) break;
980  cell_def new_cell_def;
981  // Tokenize the line
982  tokens = ReadRTT::split_string( line, ' ' );
983  new_cell_def.id = std::atoi( tokens[0].c_str() );
984  new_cell_def.name = tokens[1];
985  // Getting the number of nodes and sides
986  std::getline( input_file, line );
987  // Tokenize the line
988  tokens = ReadRTT::split_string( line, ' ' );
989  new_cell_def.nnodes = std::atoi( tokens[0].c_str() );
990  new_cell_def.nsides = std::atoi( tokens[1].c_str() );
991  // Side type index
992  std::getline( input_file, line );
993  // Tokenize the line
994  tokens = ReadRTT::split_string( line, ' ' );
995  for( int i = 0; i < new_cell_def.nsides; i++ )
996  {
997  int side_type = std::atoi( tokens[i].c_str() );
998  new_cell_def.side_type.push_back( side_type );
999  }
1000  // Read the nodes per side
1001  for( int i = 0; i < new_cell_def.nsides; i++ )
1002  {
1003  std::vector< int > side_nodes;
1004  std::getline( input_file, line );
1005  // Tokenize the line
1006  tokens = ReadRTT::split_string( line, ' ' );
1007  for( int j = 0; j < new_cell_def.nnodes; j++ )
1008  {
1009  side_nodes.push_back( std::atoi( tokens[i].c_str() ) );
1010  }
1011  new_cell_def.sides_nodes.push_back( side_nodes );
1012  }
1013 
1014  cell_def_data.insert( std::make_pair( new_cell_def.id, new_cell_def ) );
1015  }
1016 
1017  return MB_SUCCESS;
1018 }
1019 
1020 /*
1021  * given the string sidedata, get the id number, senses and names of the sides
1022  */
1023 ReadRTT::side ReadRTT::get_side_data( std::string sidedata )
1024 {
1025  side new_side;
1026  std::vector< std::string > tokens;
1027  tokens = ReadRTT::split_string( sidedata, ' ' );
1028 
1029  // set the side id
1030  if( tokens.size() != 2 )
1031  {
1032  MB_SET_ERR_RET_VAL( "Error, too many tokens found from side_data", new_side );
1033  }
1034  // create the new side
1035  new_side.id = std::atoi( tokens[0].c_str() );
1036 
1037  std::vector< std::string > cell_names = ReadRTT::split_string( tokens[1], '/' );
1038  // get the boundary
1039  boundary new_bnd = ReadRTT::split_name( cell_names[0] );
1040  // set the surface sense and name
1041  new_side.senses[0] = new_bnd.sense;
1042  new_side.names[0] = new_bnd.name;
1043  //
1044  if( cell_names.size() > 1 )
1045  {
1046  boundary bnd = ReadRTT::split_name( cell_names[1] );
1047  new_side.senses[1] = bnd.sense;
1048  new_side.names[1] = bnd.name;
1049  }
1050  else
1051  {
1052  new_side.senses[1] = 0;
1053  new_side.names[1] = "\0";
1054  }
1055 
1056  return new_side;
1057 }
1058 
1059 /*
1060  * given the string celldata, get the id number and name of each cell
1061  */
1062 ReadRTT::cell ReadRTT::get_cell_data( std::string celldata )
1063 {
1064  cell new_cell;
1065  std::vector< std::string > tokens;
1066  tokens = ReadRTT::split_string( celldata, ' ' );
1067 
1068  // set the side id
1069  if( tokens.size() != 2 )
1070  {
1071  MB_SET_ERR_RET_VAL( "Error, too many tokens found from cell_data", new_cell );
1072  }
1073  // create the new side
1074  new_cell.id = std::atoi( tokens[0].c_str() );
1075  new_cell.name = tokens[1];
1076 
1077  return new_cell;
1078 }
1079 
1080 /*
1081  * given the string nodedata, get the id number and coordinates of the node
1082  */
1083 ReadRTT::node ReadRTT::get_node_data( std::string nodedata )
1084 {
1085  node new_node;
1086  std::vector< std::string > tokens;
1087  tokens = ReadRTT::split_string( nodedata, ' ' );
1088 
1089  // set the side id
1090  if( tokens.size() != 5 )
1091  {
1092  MB_SET_ERR_RET_VAL( "Error, too many tokens found from get_node_data", new_node );
1093  }
1094  new_node.id = std::atoi( tokens[0].c_str() );
1095  new_node.x = std::atof( tokens[1].c_str() );
1096  new_node.y = std::atof( tokens[2].c_str() );
1097  new_node.z = std::atof( tokens[3].c_str() );
1098  return new_node;
1099 }
1100 
1101 /*
1102  * given the string nodedata, get the id number, connectivity and sense data
1103  */
1104 ReadRTT::facet ReadRTT::get_facet_data( std::string facetdata )
1105 {
1106  facet new_facet;
1107  std::vector< std::string > tokens;
1108  tokens = ReadRTT::split_string( facetdata, ' ' );
1109 
1110  // ensure we have the correct number of tokens
1111  int base_token_size = 0;
1112  int idx_offset = 0;
1113  // branch on the rtt version number
1114  if( header_data.version == "v1.0.0" )
1115  {
1116  base_token_size = 4;
1117  }
1118  else if( header_data.version == "v1.0.1" )
1119  {
1120  base_token_size = 5;
1121  idx_offset = 1;
1122  }
1123  else
1124  {
1125  MB_SET_ERR_RET_VAL( "Error, version number not understood", new_facet );
1126  }
1127 
1128  if( (int)tokens.size() != base_token_size + dim_data.nside_flag_types )
1129  {
1130  std::cout << facetdata << std::endl;
1131  std::cout << header_data.version << " " << (int)tokens.size() << " " << base_token_size << " "
1132  << dim_data.nside_flag_types << std::endl;
1133  MB_SET_ERR_RET_VAL( "Error, too many tokens found from get_facet_data", new_facet );
1134  }
1135 
1136  // set the side id
1137  new_facet.id = std::atoi( tokens[0].c_str() );
1138  new_facet.connectivity[0] = std::atoi( tokens[idx_offset + 1].c_str() );
1139  new_facet.connectivity[1] = std::atoi( tokens[idx_offset + 2].c_str() );
1140  new_facet.connectivity[2] = std::atoi( tokens[idx_offset + 3].c_str() );
1141  new_facet.side_id = std::atoi( tokens[idx_offset + 4].c_str() );
1142  new_facet.surface_number = std::atoi( tokens[idx_offset + 5].c_str() );
1143 
1144  return new_facet;
1145 }
1146 
1147 /*
1148  * given the string tetdata, get the id number, connectivity and mat num of the
1149  * tet
1150  */
1151 ReadRTT::tet ReadRTT::get_tet_data( std::string tetdata )
1152 {
1153  tet new_tet;
1154  std::vector< std::string > tokens;
1155  tokens = ReadRTT::split_string( tetdata, ' ' );
1156 
1157  // ensure we have the correct number of tokens
1158  int base_token_size = 0;
1159  int n_nodes = 0;
1160  // branch on the rtt version number
1161  if( header_data.version == "v1.0.0" )
1162  {
1163  base_token_size = 1;
1164  // for old format we assume 4 nodes (Tet)
1165  n_nodes = 4;
1166  }
1167  else if( header_data.version == "v1.0.1" )
1168  {
1169  base_token_size = 2;
1170 
1171  // get the cell type
1172  new_tet.type_id = std::atoi( tokens[1].c_str() );
1173  // check that the cell type exists
1174  if( cell_def_data.find( new_tet.type_id ) == cell_def_data.end() )
1175  {
1176  std::cout << "Error: cell type " << new_tet.type_id << " not found in cell definitions." << std::endl;
1177  MB_SET_ERR_RET_VAL( "Error, cell type not found in cell definitions", new_tet );
1178  }
1179  n_nodes = cell_def_data[new_tet.type_id].nnodes;
1180  int n_sides = cell_def_data[new_tet.type_id].nsides;
1181  if( n_nodes != 4 || n_sides != 4 )
1182  {
1183  std::cout << "Error: cell type " << new_tet.type_id << " does not have 4 nodes and 4 sides." << std::endl;
1184  MB_SET_ERR_RET_VAL( "Error, cell is not tetrahedricon", new_tet );
1185  }
1186  }
1187  else
1188  {
1189  MB_SET_ERR_RET_VAL( "Error, version number not understood", new_tet );
1190  }
1191  // set the side id
1192  new_tet.id = std::atoi( tokens[0].c_str() );
1193 
1194  if( (int)tokens.size() != base_token_size + n_nodes + dim_data.ncell_flag_types )
1195  {
1196  MB_SET_ERR_RET_VAL( "Error, unexpected number of tokens found from get_tet_data", new_tet );
1197  }
1198  for( int i = 0; i < n_nodes; i++ )
1199  {
1200  new_tet.connectivity[i] = std::atoi( tokens[i + base_token_size].c_str() );
1201  }
1202  for( int i = 0; i < dim_data.ncell_flag_types; i++ )
1203  {
1204  new_tet.flag_values.push_back( std::atoi( tokens[i + base_token_size + n_nodes].c_str() ) );
1205  }
1206 
1207  return new_tet;
1208 }
1209 
1210 /*
1211 * given the cell data, get the maximum name size
1212 */
1213 int ReadRTT::get_max_name_size( std::vector< cell > cell_data )
1214 {
1215  int max_size = 0;
1216  for( size_t i = 0; i < cell_data.size(); i++ )
1217  {
1218  if( (int)cell_data[i].name.length() > max_size ) max_size = cell_data[i].name.length();
1219  }
1220  return max_size;
1221 }
1222 
1223 /*
1224  * splits string into sense and name, to later facilitate the building
1225  * of sense data, strips off the tailing @ if it exists
1226  */
1227 ReadRTT::boundary ReadRTT::split_name( std::string atilla_cellname )
1228 {
1229  boundary new_boundary;
1230  // default initialisation
1231  new_boundary.sense = 0;
1232  new_boundary.name = "\0";
1233  // +ve sense
1234  if( atilla_cellname.find( "+" ) != std::string::npos )
1235  {
1236  new_boundary.sense = 1;
1237  // look for the @# we do not want it
1238  std::size_t found = atilla_cellname.find( "@" );
1239  if( found != std::string::npos )
1240  new_boundary.name = atilla_cellname.substr( 3, found );
1241  else
1242  new_boundary.name = atilla_cellname.substr( 3, atilla_cellname.length() );
1243  }
1244  else if( atilla_cellname.find( "-" ) != std::string::npos )
1245  {
1246  // negative sense
1247  new_boundary.sense = -1;
1248  new_boundary.name = atilla_cellname.substr( 3, atilla_cellname.length() );
1249  }
1250  return new_boundary;
1251 }
1252 
1253 /*
1254  * splits a string in a vector of strings split by spaces
1255  */
1256 std::vector< std::string > ReadRTT::split_string( std::string string_to_split, char split_char )
1257 {
1258  std::istringstream ss( string_to_split );
1259  std::vector< std::string > tokens;
1260  while( !ss.eof() )
1261  {
1262  std::string x; // here's a nice, empty string
1263  std::getline( ss, x, split_char ); // try to read the next field into it
1264  tokens.push_back( x );
1265  }
1266 
1267  // remove empty tokens
1268  std::vector< std::string >::iterator it;
1269  for( it = tokens.begin(); it != tokens.end(); )
1270  {
1271  std::string string = *it;
1272  if( string.compare( "\0" ) == 0 )
1273  it = tokens.erase( it );
1274  else
1275  ++it;
1276  }
1277  return tokens;
1278 }
1279 
1280 /*
1281  * Generate the parent-child links bwetween the cell and surface meshsets
1282  */
1284  std::vector< EntityHandle > entity_map[4],
1285  std::vector< side > side_data,
1286  std::vector< cell > cell_data )
1287 {
1288  ErrorCode rval; // return value
1289  // loop over the number of surfaces
1290  for( int i = 0; i < num_ents[2]; i++ )
1291  {
1292  // get the surface handle
1293  EntityHandle surf_handle = entity_map[2][i];
1294  // there are volumes that share this face
1295  for( unsigned int shared = 0; shared <= 1; shared++ )
1296  {
1297  std::string parent_name = side_data[i].names[shared];
1298  // find the @ sign
1299  unsigned pos = parent_name.find( "@" );
1300  parent_name = parent_name.substr( 0, pos );
1301 
1302  // loop over tets looking for matching name
1303  for( int j = 0; j < num_ents[3]; j++ )
1304  {
1305  // if match found
1306  if( cell_data[j].name.compare( parent_name ) == 0 )
1307  {
1308  EntityHandle cell_handle = entity_map[3][j];
1309  // parent
1310  rval = MBI->add_parent_child( cell_handle, surf_handle );
1311  if( rval != MB_SUCCESS )
1312  {
1313  std::cerr << "Failed to add parent child relationship" << std::endl;
1314  }
1315  }
1316  }
1317  }
1318  }
1319  return;
1320 }
1321 
1322 /*
1323  * sets the sense of the surfaces wrt to volumes using geom topo tool
1324  */
1325 void ReadRTT::set_surface_senses( int num_ents[4],
1326  std::vector< EntityHandle > entity_map[4],
1327  std::vector< side > side_data,
1328  std::vector< cell > cell_data )
1329 {
1330 
1331  ErrorCode rval; // return value
1332  // loop over the number of surfaces
1333  for( int i = 0; i < num_ents[2]; i++ )
1334  {
1335  EntityHandle surf_handle = entity_map[2][i];
1336  // there are 2 volumes that share this face
1337  for( unsigned int shared = 0; shared <= 1; shared++ )
1338  {
1339  std::string parent_name = side_data[i].names[shared];
1340  unsigned pos = parent_name.find( "@" );
1341  parent_name = parent_name.substr( 0, pos );
1342  // loop over tets looking for matching name
1343  for( int j = 0; j < num_ents[3]; j++ )
1344  {
1345  // if match found
1346  if( cell_data[j].name.compare( parent_name ) == 0 )
1347  {
1348  EntityHandle cell_handle = entity_map[3][j];
1349  // in rtt mesh +represents the inside and -represents outside
1350  // in moab reverse is outside and forward is inside
1351  if( side_data[i].senses[shared] == 1 )
1352  rval = myGeomTool->set_sense( surf_handle, cell_handle, SENSE_FORWARD );
1353  else if( side_data[i].senses[shared] == -1 )
1354  rval = myGeomTool->set_sense( surf_handle, cell_handle, SENSE_REVERSE );
1355  else
1356  rval = myGeomTool->set_sense( surf_handle, 0, SENSE_REVERSE );
1357 
1358  if( rval != MB_SUCCESS )
1359  {
1360  std::cerr << "Failed to set sense appropriately" << std::endl;
1361  }
1362  }
1363  }
1364  }
1365  }
1366  return;
1367 }
1368 
1369 /*
1370  * Add all entities that are to be part of the graveyard
1371  */
1372 ErrorCode ReadRTT::setup_group_data( std::vector< EntityHandle > entity_map[4],
1373  std::vector< tet > tet_data,
1374  std::map< int, EntityHandle >& volume_map )
1375 {
1376  ErrorCode rval; // error codes
1377  EntityHandle handle;
1378  handle = create_group( "graveyard_comp", 1 );
1379  if( handle == 0 ) return MB_FAILURE;
1380 
1381  // add any volume to group graveyard, it is ignored by dag
1382  EntityHandle vol_handle = entity_map[3][0];
1383  rval = MBI->add_entities( handle, &vol_handle, 1 );
1384  if( rval != MB_SUCCESS ) return rval;
1385 
1386  if( get_material_ref_flag() == "MATERIAL" )
1387  {
1388  std::string mat_flag = get_material_ref_flag();
1389  std::string vol_flag = get_volume_ref_flag();
1390  const std::vector< cell >& mat_cells = cell_flag_datas[mat_flag];
1391  const std::map< int, int >& mat_idx = cell_flag_indexes[mat_flag];
1392 
1393  std::map< int, int > volume2mat; // region → material
1394  std::map< int, EntityHandle > mat_groups; // material → group
1395 
1396  for( const auto& t : tet_data )
1397  {
1398  int mat_no = t.flag_values[cell_flag_idx[mat_flag]];
1399  int vol_no = t.flag_values[cell_flag_idx[vol_flag]];
1400 
1401  // record the material of this volume (consistency check)
1402  auto it = volume2mat.find( vol_no );
1403  if( it == volume2mat.end() )
1404  volume2mat[vol_no] = mat_no;
1405  else if( it->second != mat_no )
1406  {
1407  std::cerr << "Volume " << vol_no << " has conflicting material numbers: " << it->second << " and "
1408  << mat_no << std::endl;
1409  return MB_FAILURE;
1410  }
1411 
1412  // create material group the first time we meet this material
1413  if( mat_groups.find( mat_no ) == mat_groups.end() )
1414  {
1415  std::string name = mat_cells[mat_idx.at( mat_no )].name;
1416  if( name.rfind( "mat:", 0 ) != 0 ) name = "mat:" + name; // exactly one prefix
1417 
1418  EntityHandle mat_grp;
1419  MB_CHK_ERR( create_material_group( name, mat_no, mat_grp ) );
1420  mat_groups[mat_no] = mat_grp;
1421  }
1422  }
1423 
1424  // assigning volumes to material groups
1425  for( const auto& vp : volume2mat )
1426  {
1427  int vol_no = vp.first;
1428  int mat_no = vp.second;
1429  auto v_it = volume_map.find( vol_no );
1430  auto m_it = mat_groups.find( mat_no );
1431 
1432  if( v_it == volume_map.end() || m_it == mat_groups.end() )
1433  {
1434  std::cerr << "Missing handle while adding volume " << vol_no << " to material " << mat_no << std::endl;
1435  return MB_FAILURE;
1436  }
1437  EntityHandle vol_h = v_it->second;
1438  EntityHandle grp_h = m_it->second;
1439 
1440  MB_CHK_ERR( MBI->add_entities( grp_h, &vol_h, 1 ) );
1441  }
1442  }
1443 
1444  return rval;
1445 }
1446 
1447 /*
1448  * create a new group of with the name group name and id
1449  */
1450 EntityHandle ReadRTT::create_group( std::string group_name, int id )
1451 {
1452  ErrorCode rval;
1453  // category tags
1454  const char geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0", "Group\0" };
1455 
1456  EntityHandle handle;
1458 
1459  char name_buf[NAME_TAG_SIZE] = { 0 };
1460  std::strncpy( name_buf, group_name.c_str(), NAME_TAG_SIZE - 1 );
1461  MB_CHK_ERR(MBI->tag_set_data( name_tag, &handle, 1, name_buf ));
1462 
1463  MB_CHK_ERR(MBI->tag_set_data( id_tag, &handle, 1, &id ));
1464 
1465  MB_CHK_ERR(MBI->tag_set_data( category_tag, &handle, 1, &geom_categories[4] ));
1466 
1467  return handle;
1468 }
1469 
1470 } // namespace moab