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 #ifndef MOAB_WRITE_UTIL_IFACE_HPP
17 #define MOAB_WRITE_UTIL_IFACE_HPP
18
19 #include "moab/Range.hpp"
20 #include "moab/Compiler.hpp"
21 #include <vector>
22
23 namespace moab
24 {
25
26 //! Interface implemented in MOAB which provides memory for mesh reading utilities
27 class WriteUtilIface
28 {
29 public:
30 //! Constructor
31 WriteUtilIface() {}
32
33 //! Destructor
34 virtual ~WriteUtilIface() {}
35
36 //! Check if the specified file already exists.
37 //! Returns MB_SUCCESS if file does not exist, MB_ALREADY_ALLOCATED
38 //! if file does exist, or MB_FAILURE for some other error condition.
39 virtual ErrorCode check_doesnt_exist( const char* file_name ) = 0;
40
41 //! Gather all entities in the mesh, or in the sets specified
42 virtual ErrorCode gather_entities(
43 Range& all_ents, /**< range in which entities are returned */
44 const EntityHandle* ent_sets = NULL, /**< entity sets whose contents are to be gathered */
45 int num_sets = 0 /**< number of sets in list */ ) = 0;
46
47 //! Given information about the nodes to be written, and pointers to memory
48 //! to which coordinates will be written, writes coordinate data there, and
49 //! also assigns global ids to nodes & writes to a tag, if a tag is specified
50 //! \param num_arrays Number of coordinate arrays requested
51 //! \param num_nodes Number of nodes to be written
52 //! \param entities Range of nodes to be written
53 //! \param node_id_tag Tag used to write ids to nodes
54 //! \param start_node_id Starting value for node ids
55 //! \param arrays Pointers to memory where coordinate data will be written
56 //! \return status Return status
57 virtual ErrorCode get_node_coords( const int num_arrays,
58 const int num_nodes,
59 const Range& entities,
60 Tag node_id_tag,
61 const int start_node_id,
62 std::vector< double* >& arrays ) = 0;
63
64 /** Get array of coordinate values for nodes
65 *
66 * Given a range of node handles, retrieve a single or multiple coordinate
67 * value(s) for each.
68 *
69 * Failure conditions:
70 * - invalid entity handles (not vertices, non-existent entity, etc.)
71 * - range is empty (<code>iter == end</code>)
72 * - <code>output_array</code> is null
73 * - insufficient space in <code>output_array</code>
74 *
75 *\param which_array The coordinate to retrieve (0->X, 1->Y, 2->Z, -1->all)
76 *\param begin The first node handle.
77 *\param end One past the last node handle.
78 *\param output_size The size of <code>output_array</code>.
79 *\param output_array The memory in which to write the node coordinates.
80 *\author Jason Kraftcheck
81 */
82 virtual ErrorCode get_node_coords( const int which_array,
83 Range::const_iterator begin,
84 const Range::const_iterator& end,
85 const size_t output_size,
86 double* const output_array ) = 0;
87
88 //! Given information about elements to be written and a pointer to memory
89 //! where connectivity for those elements should be written, writes connectivity
90 //! to that memory; uses node ids stored in a tag during call to <em>get_node_coords</em>
91 //! function
92 //! \param num_elements Number of elements to be written
93 //! \param verts_per_element Number of vertices per element
94 //! \param node_id_tag Tag used to store node ids
95 //! \param entities Range of elements to be written
96 //! \param element_id_tag Tag which should be used to store element ids
97 //! \param start_element_id Starting value for element ids
98 //! \param array Pointer to memory where connectivity data will be written
99 //! \return status Return status
100 virtual ErrorCode get_element_connect( const int num_elements,
101 const int verts_per_element,
102 Tag node_id_tag,
103 const Range& entities,
104 Tag element_id_tag,
105 int start_element_id,
106 int* array,
107 bool add_sizes = false ) = 0;
108
109 /** Get connectivity for elements
110 *
111 * Get the connectivity list for a range of elements.
112 *
113 * Failure cases:
114 * - Passed range is empty (<code>begin == end</code>).
115 * - <code>vertices_per_elem</code> is less than one
116 * - <code>element_array</code> is null.
117 * - The range contains invalid handles (non-existent entities,
118 * not an element, etc.)
119 * - Retrieving ID tag for an entity failed.
120 * - Insufficient space in passed array.
121 *
122 *\param begin The first element handle
123 *\param end One past the last element handle
124 *\param vertices_per_elem Number of vertices to retrieve for each
125 * element. If the element has more vertices, the
126 * element connectivity will be truncated. If
127 * <code>vertices_per_elem</code> is greater than the
128 * number of nodes for an element, the data will be
129 * padded with zeros.
130 *\param node_id_tag A tag with integer values.
131 *\param array_size The length of <code>element_array</code>
132 *\param element_array The memory location at which to store the
133 * connectivity list.
134 *\param add_sizes If true, writes size of connect array before connectivity in array
135 *\author Jason Kraftcheck
136 */
137 virtual ErrorCode get_element_connect( Range::const_iterator begin,
138 const Range::const_iterator& end,
139 const int vertices_per_elem,
140 Tag node_id_tag,
141 const size_t array_size,
142 int* const element_array,
143 bool add_sizes = false ) = 0;
144
145 /** Get connectivity for elements
146 *
147 * Get the connectivity list for a range of elements.
148 *
149 * Failure cases:
150 * - Passed range is empty (<code>begin == end</code>).
151 * - <code>vertices_per_elem</code> is less than one
152 * - <code>element_array</code> is null.
153 * - The range contains invalid handles (non-existent entities,
154 * not an element, etc.)
155 * - Insufficient space in passed array.
156 *
157 *\param begin The first element handle
158 *\param end One past the last element handle
159 *\param vertices_per_elem Number of vertices to retrieve for each
160 * element. If the element has more vertices, the
161 * element connectivity will be truncated. If
162 * <code>vertices_per_elem</code> is greater than the
163 * number of nodes for an element, the data will be
164 * padded with zeros.
165 *\param array_size The length of <code>element_array</code>
166 *\param element_array The memory location at which to store the
167 * connectivity list.
168 *\author Jason Kraftcheck
169 */
170 virtual ErrorCode get_element_connect( Range::const_iterator begin,
171 const Range::const_iterator& end,
172 const int vertices_per_elem,
173 const size_t array_size,
174 EntityHandle* const element_array ) = 0;
175
176 /** Get poly (polygon or polyhedron) connectivity size
177 *\param begin First iterator in range of poly
178 *\param end One past last in range of poly.
179 *\param connectivity_size The length of the connectivity list
180 * For the specified range of polyhedra.
181 *\author Jason Kraftcheck
182 */
183 virtual ErrorCode get_poly_connect_size( Range::const_iterator begin,
184 const Range::const_iterator& end,
185 int& connectivity_size ) = 0;
186
187 /** Get poly (polygon or polyhedron) connectivity.
188 *
189 * Connectivity is returned in two arrays. The first is
190 * an array of global IDs that is the concatenation of the
191 * connectivity for the entire range of polys. The second
192 * is the last index of the connectivity data for each poly
193 * in the global ID array.
194 *
195 * This function will add as many polys as possible to the
196 * passed arrays given the sizes of those arrays. It will
197 * then pass back position at which it stopped and the sizes
198 * of the data written to the arrays.
199 *
200 * Failure cases:
201 * - Passed range is empty (<code>begin == end</code>).
202 * - <code>element_array</code> or <code>index_array</code> is null.
203 * - The range contains invalid handles (non-existent entities,
204 * not an poly, etc.)
205 * - Retrieving ID tag for an entity failed.
206 *
207 *\param iter As input, the first element handle.
208 * As output, one past the last element handle
209 * for which data was written to the arrays.
210 *\param end The iterator at which to stop.
211 *\param node_id_tag A tag with integer values.
212 *\param element_array_len As input, length of <code>element_array</code>.
213 * As output, the number of entries written in that
214 * array.
215 *\param element_array The memory location at which to store the
216 * connectivity list.
217 *\param index_array_len As input, the length of <code>index_array</code>.
218 * As output, the number of entries written in that
219 * array.
220 *\param index_array The memory location at which to store offsets.
221 *\param index_offset Value to offset (add to) index values. As output
222 * the input value plus the amount of data
223 * written to the element array. (The value you
224 * presumably want to pass to the next call.)
225 *\author Jason Kraftcheck
226 */
227 virtual ErrorCode get_poly_connect( Range::const_iterator& iter,
228 const Range::const_iterator& end,
229 const Tag node_id_tag,
230 size_t& element_array_len,
231 int* const element_array,
232 size_t& index_array_len,
233 int* const index_array,
234 int& index_offset ) = 0;
235
236 //! Given elements to be written, gather all the nodes which define those elements
237 //! \param elements Range of elements to be written
238 //! \param node_bit_mark_tag Bit tag to use to identify nodes
239 //! \param nodes Range of nodes gathered from elements (returned)
240 //! \return status Return status
241 virtual ErrorCode gather_nodes_from_elements( const Range& elements,
242 const Tag node_bit_mark_tag,
243 Range& nodes ) = 0;
244
245 //! assign ids to input entities starting with start_id, written to id_tag
246 //! if id_tag is zero, assigns to GLOBAL_ID_TAG_NAME
247 //! \param elements Entities to be written
248 //! \param id_tag Tag used to store entity id
249 //! \param start_id Starting value for entity ids
250 //! \return status Return status
251 virtual ErrorCode assign_ids( Range& elements, Tag id_tag, const int start_id ) = 0;
252
253 /** Get explicit adjacencies
254 *
255 * Get explicit adjacences stored in database.
256 * Does not create any explicit adjacencies or search for
257 * implicit ones.
258 *
259 *\param entity The entity to retrieve adjacencies for.
260 *\param id_tag The global ID tag
261 *\param adj The output list of global IDs of adjacent entities.
262 *\author Jason Kraftcheck
263 */
264 virtual ErrorCode get_adjacencies( EntityHandle entity, Tag id_tag, std::vector< int >& adj ) = 0;
265
266 virtual ErrorCode get_adjacencies( EntityHandle entity, const EntityHandle*& adj_array, int& num_adj ) = 0;
267
268 /**\brief Re-order outgoing element connectivity
269 *
270 * Permute the connectivity of each element such that the node
271 * order is that of the target file format rather than that of MBCN.
272 *\param order The permutation to use. Must be an array of 'node_per_elem'
273 * integers and be a permutation of the values [0..node_per_elem-1].
274 * Such that for a single element:
275 * target_conn[i] == mbcn_conn[order[i]]
276 *\param conn The connectivity array to re-order
277 *\param num_elem The number of elements in the connectivity array
278 *\param node_per_elem The number of nodes in each element's connectivity list.
279 */
280 template < typename T >
281 static inline void reorder( const int* order, T* conn, int num_elem, int node_per_elem );
282
283 /**\brief Get list of tags to write.
284 *
285 * Get the list of tags to write to the file, possibly using
286 * an optional user-specified tag list. This function consolidates
287 * some common code for file writers to use to figure out what
288 * tag data to write to the file. It provides the following features:
289 * o filter list based on user-specified array of tag handles
290 * o filter internal tags (those for which the name is prefixed with
291 * two underscore characters)
292 * o filter anonymous tags
293 * o optionally filter variable-length tags.
294 *
295 *\author Jason Kraftcheck
296 *\param result_list List of tag handles for which to write data
297 *\param user_tag_list Optional array of tag handles passed by user
298 * to write to file.
299 *\param include_variable_length_tags If false, return only fixed-length
300 * tags.
301 */
302 virtual ErrorCode get_tag_list( std::vector< Tag >& result_list,
303 const Tag* user_tag_list = 0,
304 int user_tag_list_length = 0,
305 bool include_variable_length_tags = true ) = 0;
306
307 enum EntityListType
308 {
309 CONTENTS = 0,
310 CHILDREN = 1,
311 PARENTS = 2,
312 TOPOLOGICAL = 1
313 };
314
315 /*\brief Get pointers to internal storage of entity data
316 *
317 * Get pointers to element connectivity or set content storage.
318 *\param query_begin Start of range of entities for which to return results
319 *\param query_end End of range of entities for which to return results.
320 *\param output_pointer_array Result list of pointers. Points to either
321 * element connectivity or set contents. Note: set contents
322 * may be in range-compacted format.
323 *\param lengths Optional per-entity length of list. If passed, then
324 * always set, for each entity, to the number of values in the
325 * array passed back in \c output_pointer_array
326 *\param relation If entity is entity set, which set data to return
327 * (contents array, parent array, or child array). If
328 * entity is an element, then CONTENTS for complete connectivity
329 * or TOPOLOGICAL for only corner vertices.
330 *\param flags Optional per-entity flag values. If passed, then
331 * always set to zero for elements and set to set creation
332 * flags for entity sets.
333 *\return MB_STRUCTURED_MESH if one or more input elements are stored as
334 * structured mesh and therefore do not have explicit storage.
335 * MB_TYPE_OUT_OF_RANGE if called for vertices.
336 */
337 virtual ErrorCode get_entity_list_pointers( Range::const_iterator query_begin,
338 Range::const_iterator query_end,
339 EntityHandle const** output_pointer_array,
340 EntityListType relation = CONTENTS,
341 int* lengths = 0,
342 unsigned char* flags = 0 ) = 0;
343
344 /*\brief Get pointers to internal storage of entity data
345 *
346 * Get pointers to element connectivity or set content storage.
347 *\param entities Pointer to list of entities for which to return results
348 *\param num_entities Number of entities in list
349 *\param output_pointer_array Result list of pointers. Points to either
350 * element connectivity or set contents. Note: set contents
351 * may be in range-compacted format.
352 *\param lengths Optional per-entity length of list. If passed, then
353 * always set, for each entity, to the number of values in the
354 * array passed back in \c output_pointer_array
355 *\param relation If entity is entity set, which set data to return
356 * (contents array, parent array, or child array). If
357 * entity is an element, then CONTENTS for complete connectivity
358 * or TOPOLOGICAL for only corner vertices.
359 *\param flags Optional per-entity flag values. If passed, then
360 * always set to zero for elements and set to set creation
361 * flags for entity sets.
362 *\return MB_STRUCTURED_MESH if one or more input elements are stored as
363 * structured mesh and therefore do not have explicit storage.
364 * MB_TYPE_OUT_OF_RANGE if called for vertices.
365 */
366 virtual ErrorCode get_entity_list_pointers( EntityHandle const* entities,
367 int num_entities,
368 EntityHandle const** output_pointer_array,
369 EntityListType relation = CONTENTS,
370 int* lengths = 0,
371 unsigned char* flags = 0 ) = 0;
372 };
373
374 template < typename T >
375 inline void WriteUtilIface::reorder( const int* order, T* conn, int num_elem, int node_per_elem )
376 {
377 std::vector< T > elem( node_per_elem );
378 T* const end = conn + num_elem * node_per_elem;
379 while( conn != end )
380 {
381 std::copy( conn, conn + node_per_elem, elem.begin() );
382 for( int j = 0; j < node_per_elem; ++j, ++conn )
383 *conn = elem[order[j]];
384 }
385 }
386
387 } // namespace moab
388
389 #endif