Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
ReadTemplate.cpp
Go to the documentation of this file.
1 /**
2  * \class ReadTemplate
3  * \brief Template for writing a new reader in MOAB
4  *
5  */
6 
7 #include "ReadTemplate.hpp"
8 #include "moab/Interface.hpp"
9 #include "moab/ReadUtilIface.hpp"
10 #include "moab/Range.hpp"
11 #include "moab/FileOptions.hpp"
12 
13 #include <cstdio>
14 #include <cassert>
15 
16 namespace moab
17 {
18 
20 {
21  return new ReadTemplate( iface );
22 }
23 
24 ReadTemplate::ReadTemplate( Interface* impl ) : mbImpl( impl ), fileName( NULL )
25 {
27 }
28 
30 {
31  if( readMeshIface )
32  {
34  readMeshIface = 0;
35  }
36 }
37 
38 ErrorCode ReadTemplate::read_tag_values( const char* /* file_name */,
39  const char* /* tag_name */,
40  const FileOptions& /* opts */,
41  std::vector< int >& /* tag_values_out */,
42  const SubsetList* /* subset_list */ )
43 {
44  return MB_NOT_IMPLEMENTED;
45 }
46 
47 ErrorCode ReadTemplate::load_file( const char* filename,
48  const EntityHandle* file_set,
49  const FileOptions& opts,
50  const ReaderIface::SubsetList* subset_list,
51  const Tag* /*file_id_tag*/ )
52 {
53  if( subset_list )
54  {
55  // See src/moab/ReaderIface.hpp, definition of SubsetList struct; this basically specifies
56  // an integer tag and tag values for sets to read on this proc, or a part number and total #
57  // parts for reading a trivial partition of entities
58  }
59 
60  // Save filename to member variable so we don't need to pass as an argument
61  // to called functions
62  fileName = filename;
63 
64  // Process options; see src/FileOptions.hpp for API for FileOptions class, and
65  // doc/metadata_info.doc for a description of various options used by some of the readers in
66  // MOAB
67  ErrorCode result = process_options( opts );
68  MB_CHK_SET_ERR( result, fileName << ": problem reading options" );
69 
70  // Open file; filePtr is member of ReadTemplate, change to whatever mechanism is used to
71  // identify file
72  FILE* filePtr = fopen( fileName, "r" );
73  if( !filePtr )
74  {
75  MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error" );
76  }
77 
78  // Read number of verts, elements, sets
79  long num_verts = 0, num_elems = 0, num_sets = 0;
80 
81  // read_ents keeps a running set of entities read from this file, including vertices, elements,
82  // and sets; these will get added to file_set (if input) at the end of the read
83  Range read_ents;
84 
85  // start_vertex is passed back so we know how to convert indices from the file into vertex
86  // handles; most of the time this is done by adding start_vertex to the (0-based) index; if the
87  // index is 1-based, you also need to subtract one; see read_elements for details
88  EntityHandle start_vertex;
89  result = read_vertices( num_verts, start_vertex, read_ents );
90  if( MB_SUCCESS != result )
91  {
92  fclose( filePtr );
93  return result;
94  }
95 
96  // Create/read elements; this template assumes that all elements are the same type, so can be
97  // read in a single call to read_elements, and kept track of with a single start_elem handle. If
98  // there are more entity types, might have to keep these start handles in an array/vector.
99  // start_elem is only really needed if you're reading sets later, and need to convert some
100  // file-based index to an entity handle
101  EntityHandle start_elem;
102  result = read_elements( num_elems, start_vertex, start_elem, read_ents );
103  if( MB_SUCCESS != result )
104  {
105  fclose( filePtr );
106  return result;
107  }
108 
109  // Read/create entity sets; typically these sets have some tag identifying what they're for, see
110  // doc/metadata_info.doc for examples of different kinds of sets and how they're marked
111  result = create_sets( num_sets, start_vertex, num_verts, start_elem, num_elems, read_ents );
112  if( MB_SUCCESS != result )
113  {
114  fclose( filePtr );
115  return result;
116  }
117 
118  // Finally, add all read_ents into the file set, if one was input
119  if( file_set && *file_set )
120  {
121  result = mbImpl->add_entities( *file_set, read_ents );
122  if( MB_SUCCESS != result )
123  {
124  fclose( filePtr );
125  return result;
126  }
127  }
128 
129  fclose( filePtr );
130 
131  return result;
132 }
133 
134 ErrorCode ReadTemplate::read_vertices( int num_verts, EntityHandle& start_vertex, Range& read_ents )
135 {
136  // Allocate nodes; these are allocated in one shot, get contiguous handles starting with
137  // start_handle, and the reader is passed back double*'s pointing to MOAB's native storage for
138  // vertex coordinates for those verts
139  std::vector< double* > coord_arrays;
140  ErrorCode result = readMeshIface->get_node_coords( 3, num_verts, 1, start_vertex, coord_arrays );
141  MB_CHK_SET_ERR( result, fileName << ": Trouble reading vertices" );
142 
143  // Fill in vertex coordinate arrays
144  double *x = coord_arrays[0], *y = coord_arrays[1], *z = coord_arrays[2];
145  for( long i = 0; i < num_verts; ++i )
146  {
147  // Read x/y/z; do something with them for now to avoid warning
148  if( x || y || z )
149  {
150  }
151  }
152 
153  if( num_verts ) read_ents.insert( start_vertex, start_vertex + num_verts - 1 );
154 
155  return result;
156 }
157 
158 //! Read/create elements
160  EntityHandle start_vertex,
161  EntityHandle& start_elem,
162  Range& read_ents )
163 {
164  // Get the entity type being read
165  EntityType ent_type = MBHEX;
166 
167  // Get the number of vertices per entity
168  int verts_per_elem = 8;
169 
170  // Create the element sequence; passes back a pointer to the internal storage for connectivity
171  // and the starting entity handle
172  EntityHandle* conn_array;
173  ErrorCode result =
174  readMeshIface->get_element_connect( num_elems, verts_per_elem, ent_type, 1, start_elem, conn_array );
175  MB_CHK_SET_ERR( result, fileName << ": Trouble reading elements" );
176 
177  // Read connectivity into conn_array directly
178  for( long i = 0; i < num_elems; i++ )
179  {
180  // Read connectivity
181  }
182 
183  // Convert file-based connectivity indices to vertex handles in-place; be careful, if indices
184  // are smaller than handles, need to do from the end of the list so we don't overwrite data
185  //
186  // Here, we assume indices are smaller than handles, just for demonstration; create an
187  // integer-type pointer to connectivity initialized to same start of connectivity array
188  int* ind_array = reinterpret_cast< int* >( conn_array );
189  // OFFSET is value of first vertex index in file; most files are 1-based, but some might be
190  // 0-based
191  int OFFSET = 1;
192  for( long i = num_elems * verts_per_elem - 1; i >= 0; i-- )
193  {
194  conn_array[i] = ind_array[i] + start_vertex + OFFSET;
195 
196  // This assert assumes last handle in read_ents is highest vertex handle in this file
197  assert( conn_array[i] >= start_vertex && conn_array[i] <= *read_ents.rbegin() );
198  }
199 
200  // Notify MOAB of the new elements
201  result = readMeshIface->update_adjacencies( start_elem, num_elems, verts_per_elem, conn_array );
202  if( MB_SUCCESS != result ) return result;
203 
204  // Add elements to read_ents
205  if( num_elems ) read_ents.insert( start_elem, start_elem + num_elems - 1 );
206 
207  return MB_SUCCESS;
208 }
209 
210 //! Read/create sets
212  EntityHandle /*start_vertex*/,
213  int /*num_verts*/,
214  EntityHandle /*start_elem*/,
215  int /*num_elems*/,
216  Range& read_ents )
217 {
218  ErrorCode result = MB_SUCCESS;
219  EntityHandle this_set;
220 
221  for( int i = 0; i < num_sets; i++ )
222  {
223  // Create set
224  result = mbImpl->create_meshset( MESHSET_SET, this_set );
225  MB_CHK_SET_ERR( result, fileName << ": Trouble creating set" );
226 
227  Range set_ents;
228  // Read/compute what's in this set; REMEMBER TO CONVERT THESE TO MOAB HANDLES
229 
230  // Add them to the set
231  result = mbImpl->add_entities( this_set, set_ents );
232  MB_CHK_SET_ERR( result, fileName << ": Trouble putting entities in set" );
233 
234  // Add the new set to read_ents
235  read_ents.insert( this_set );
236  }
237 
238  return MB_SUCCESS;
239 }
240 
242 {
243  // Mark all options seen, to avoid compile warning on unused variable
244  opts.mark_all_seen();
245  return MB_SUCCESS;
246 }
247 
248 } // namespace moab