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
19 ReaderIface* ReadTemplate::factory( Interface* iface )
20 {
21 return new ReadTemplate( iface );
22 }
23
24 ReadTemplate::ReadTemplate( Interface* impl ) : mbImpl( impl ), fileName( NULL )
25 {
26 mbImpl->query_interface( readMeshIface );
27 }
28
29 ReadTemplate::~ReadTemplate()
30 {
31 if( readMeshIface )
32 {
33 mbImpl->release_interface( readMeshIface );
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 );MB_CHK_SET_ERR( result, fileName << ": problem reading options" );
68
69 // Open file; filePtr is member of ReadTemplate, change to whatever mechanism is used to
70 // identify file
71 FILE* filePtr = fopen( fileName, "r" );
72 if( !filePtr )
73 {
74 MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error" );
75 }
76
77 // Read number of verts, elements, sets
78 long num_verts = 0, num_elems = 0, num_sets = 0;
79
80 // read_ents keeps a running set of entities read from this file, including vertices, elements,
81 // and sets; these will get added to file_set (if input) at the end of the read
82 Range read_ents;
83
84 // start_vertex is passed back so we know how to convert indices from the file into vertex
85 // handles; most of the time this is done by adding start_vertex to the (0-based) index; if the
86 // index is 1-based, you also need to subtract one; see read_elements for details
87 EntityHandle start_vertex;
88 result = read_vertices( num_verts, start_vertex, read_ents );
89 if( MB_SUCCESS != result )
90 {
91 fclose( filePtr );
92 return result;
93 }
94
95 // Create/read elements; this template assumes that all elements are the same type, so can be
96 // read in a single call to read_elements, and kept track of with a single start_elem handle. If
97 // there are more entity types, might have to keep these start handles in an array/vector.
98 // start_elem is only really needed if you're reading sets later, and need to convert some
99 // file-based index to an entity handle
100 EntityHandle start_elem;
101 result = read_elements( num_elems, start_vertex, start_elem, read_ents );
102 if( MB_SUCCESS != result )
103 {
104 fclose( filePtr );
105 return result;
106 }
107
108 // Read/create entity sets; typically these sets have some tag identifying what they're for, see
109 // doc/metadata_info.doc for examples of different kinds of sets and how they're marked
110 result = create_sets( num_sets, start_vertex, num_verts, start_elem, num_elems, read_ents );
111 if( MB_SUCCESS != result )
112 {
113 fclose( filePtr );
114 return result;
115 }
116
117 // Finally, add all read_ents into the file set, if one was input
118 if( file_set && *file_set )
119 {
120 result = mbImpl->add_entities( *file_set, read_ents );
121 if( MB_SUCCESS != result )
122 {
123 fclose( filePtr );
124 return result;
125 }
126 }
127
128 fclose( filePtr );
129
130 return result;
131 }
132
133 ErrorCode ReadTemplate::read_vertices( int num_verts, EntityHandle& start_vertex, Range& read_ents )
134 {
135 // Allocate nodes; these are allocated in one shot, get contiguous handles starting with
136 // start_handle, and the reader is passed back double*'s pointing to MOAB's native storage for
137 // vertex coordinates for those verts
138 std::vector< double* > coord_arrays;
139 ErrorCode result = readMeshIface->get_node_coords( 3, num_verts, 1, start_vertex, coord_arrays );MB_CHK_SET_ERR( result, fileName << ": Trouble reading vertices" );
140
141 // Fill in vertex coordinate arrays
142 double *x = coord_arrays[0], *y = coord_arrays[1], *z = coord_arrays[2];
143 for( long i = 0; i < num_verts; ++i )
144 {
145 // Read x/y/z; do something with them for now to avoid warning
146 if( x || y || z )
147 {
148 }
149 }
150
151 if( num_verts ) read_ents.insert( start_vertex, start_vertex + num_verts - 1 );
152
153 return result;
154 }
155
156 //! Read/create elements
157 ErrorCode ReadTemplate::read_elements( int num_elems,
158 EntityHandle start_vertex,
159 EntityHandle& start_elem,
160 Range& read_ents )
161 {
162 // Get the entity type being read
163 EntityType ent_type = MBHEX;
164
165 // Get the number of vertices per entity
166 int verts_per_elem = 8;
167
168 // Create the element sequence; passes back a pointer to the internal storage for connectivity
169 // and the starting entity handle
170 EntityHandle* conn_array;
171 ErrorCode result =
172 readMeshIface->get_element_connect( num_elems, verts_per_elem, ent_type, 1, start_elem, conn_array );MB_CHK_SET_ERR( result, fileName << ": Trouble reading elements" );
173
174 // Read connectivity into conn_array directly
175 for( long i = 0; i < num_elems; i++ )
176 {
177 // Read connectivity
178 }
179
180 // Convert file-based connectivity indices to vertex handles in-place; be careful, if indices
181 // are smaller than handles, need to do from the end of the list so we don't overwrite data
182 //
183 // Here, we assume indices are smaller than handles, just for demonstration; create an
184 // integer-type pointer to connectivity initialized to same start of connectivity array
185 int* ind_array = reinterpret_cast< int* >( conn_array );
186 // OFFSET is value of first vertex index in file; most files are 1-based, but some might be
187 // 0-based
188 int OFFSET = 1;
189 for( long i = num_elems * verts_per_elem - 1; i >= 0; i-- )
190 {
191 conn_array[i] = ind_array[i] + start_vertex + OFFSET;
192
193 // This assert assumes last handle in read_ents is highest vertex handle in this file
194 assert( conn_array[i] >= start_vertex && conn_array[i] <= *read_ents.rbegin() );
195 }
196
197 // Notify MOAB of the new elements
198 result = readMeshIface->update_adjacencies( start_elem, num_elems, verts_per_elem, conn_array );
199 if( MB_SUCCESS != result ) return result;
200
201 // Add elements to read_ents
202 if( num_elems ) read_ents.insert( start_elem, start_elem + num_elems - 1 );
203
204 return MB_SUCCESS;
205 }
206
207 //! Read/create sets
208 ErrorCode ReadTemplate::create_sets( int num_sets,
209 EntityHandle /*start_vertex*/,
210 int /*num_verts*/,
211 EntityHandle /*start_elem*/,
212 int /*num_elems*/,
213 Range& read_ents )
214 {
215 ErrorCode result = MB_SUCCESS;
216 EntityHandle this_set;
217
218 for( int i = 0; i < num_sets; i++ )
219 {
220 // Create set
221 result = mbImpl->create_meshset( MESHSET_SET, this_set );MB_CHK_SET_ERR( result, fileName << ": Trouble creating set" );
222
223 Range set_ents;
224 // Read/compute what's in this set; REMEMBER TO CONVERT THESE TO MOAB HANDLES
225
226 // Add them to the set
227 result = mbImpl->add_entities( this_set, set_ents );MB_CHK_SET_ERR( result, fileName << ": Trouble putting entities in set" );
228
229 // Add the new set to read_ents
230 read_ents.insert( this_set );
231 }
232
233 return MB_SUCCESS;
234 }
235
236 ErrorCode ReadTemplate::process_options( const FileOptions& opts )
237 {
238 // Mark all options seen, to avoid compile warning on unused variable
239 opts.mark_all_seen();
240 return MB_SUCCESS;
241 }
242
243 } // namespace moab