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 #include "ExoIIUtil.hpp"
17 #include "Internals.hpp"
18 #include "moab/Interface.hpp"
19 #include "moab/CN.hpp"
20 #include <cstring>
21
22 namespace moab
23 {
24
25 //
26 // definitions of ExoII-related static arrays
27 //
28
29 const EntityType ExoIIUtil::ExoIIElementMBEntity[] = {
30 MBVERTEX, // SPHERE,
31 MBEDGE, // SPRING,
32 MBEDGE, // BAR = 0,
33 MBEDGE, // BAR2,
34 MBEDGE, // BAR3,
35 MBEDGE, // BEAM,
36 MBEDGE, // BEAM2,
37 MBEDGE, // BEAM3,
38 MBEDGE, // TRUSS,
39 MBEDGE, // TRUSS2,
40 MBEDGE, // TRUSS3,
41 MBTRI, // TRI,
42 MBTRI, // TRI3,
43 MBTRI, // SHELL3,
44 MBTRI, // TRI6,
45 MBTRI, // TRI7,
46 MBQUAD, // QUAD,
47 MBQUAD, // QUAD4,
48 MBQUAD, // QUAD5,
49 MBQUAD, // QUAD8,
50 MBQUAD, // QUAD9,
51 MBQUAD, // SHELL,
52 MBQUAD, // SHELL4,
53 MBQUAD, // SHELL5,
54 MBQUAD, // SHELL8,
55 MBQUAD, // SHELL9,
56 MBTET, // TETRA,
57 MBTET, // TETRA4,
58 MBTET, // TET4
59 MBTET, // TETRA8,
60 MBTET, // TETRA10,
61 MBTET, // TETRA14,
62 MBPYRAMID, // PYRAMID,
63 MBPYRAMID, // PYRAMID5,
64 MBPYRAMID, // PYRAMID10,
65 MBPYRAMID, // PYRAMID13,
66 MBPYRAMID, // PYRAMID18,
67 MBPRISM, // WEDGE,
68 MBKNIFE, // KNIFE,
69 MBHEX, // HEX,
70 MBHEX, // HEX8,
71 MBHEX, // HEX9,
72 MBHEX, // HEX20,
73 MBHEX, // HEX27,
74 MBHEX, // HEXSHELL,
75 MBPOLYGON, // POLYGON
76 MBPOLYHEDRON, // POLYHEDRON
77 MBMAXTYPE // UNKNOWN
78 };
79
80 const char* ExoIIUtil::ElementTypeNames[] = { "SPHERE", // 0
81 "SPRING", // 1
82 "BAR", // 2
83 "BAR2", // 3
84 "BAR3", // 4
85 "BEAM", // 5
86 "BEAM2", // 6
87 "BEAM3", // 7
88 "TRUSS", // 8
89 "TRUSS2", // 9
90 "TRUSS3", // 10
91 "TRI", // 11
92 "TRI3", // 12
93 "SHELL3", // 13 really the same as TRI3; for sure in 3d?
94 "TRI6", "TRI7", "QUAD", "QUAD4", "QUAD5", "QUAD8",
95 "QUAD9", "SHELL", "SHELL4", "SHELL5", "SHELL8", "SHELL9",
96 "TETRA", "TETRA4", "TET4", "TETRA8", "TETRA10", "TETRA14",
97 "PYRAMID", "PYRAMID5", "PYRAMID10", "PYRAMID13", "PYRAMID18", "WEDGE",
98 "KNIFE", "HEX", "HEX8", "HEX9", "HEX20", "HEX27",
99 "HEXSHELL",
100 "nsided", // polygons, described differently
101 "NFACED", // polyhedra, described in faconn%d attributes
102 "UNKNOWN" };
103
104 const int ExoIIUtil::VerticesPerElement[] = {
105 1, // SPHERE
106 1, // SPRING
107 2, 2,
108 3, // BAR
109 2, 2,
110 3, // BEAM
111 2, 2,
112 3, // TRUSS
113 3, // TRI
114 3, // TRI3
115 3, // SHELL3 this is new
116 6,
117 7, // TRI
118 4, 4, 5, 8,
119 9, // QUAD
120 4, 4, 5, 8,
121 9, // SHELL
122 4, 4,
123 4, // TET4
124 8, 10,
125 14, // TETRA
126 5, 5, 10, 13,
127 18, // PYRAMID
128 6, // WEDGE
129 7, // KNIFE
130 8, 8, 9, 20,
131 27, // HEX
132 12, // HEXSHELL
133 0, // POLYGON
134 0, // POLYHEDRON
135 0 // UNKNOWN
136 };
137
138 const int ExoIIUtil::HasMidNodes[][4] = {
139 { 0, 0, 0, 0 }, // SPHERE - no mid nodes
140 { 0, 0, 0, 0 }, // SPRING - no mid nodes
141 { 0, 0, 0, 0 }, // BAR - no mid nodes, same as BAR2
142 { 0, 0, 0, 0 }, // BAR2 - no mid nodes
143 { 0, 1, 0, 0 }, // BAR3 - mid nodes on edges
144 { 0, 0, 0, 0 }, // BEAM - no mid nodes
145 { 0, 0, 0, 0 }, // BEAM2 - no mid nodes
146 { 0, 1, 0, 0 }, // BEAM3 - mid nodes on edges
147 { 0, 0, 0, 0 }, // TRUSS - no mid nodes
148 { 0, 0, 0, 0 }, // TRUSS2 - no mid nodes
149 { 0, 1, 0, 0 }, // TRUSS3 - mid nodes on edges
150 { 0, 0, 0, 0 }, // TRI - no mid nodes
151 { 0, 0, 0, 0 }, // TRI3 - no mid nodes
152 { 0, 0, 0, 0 }, // SHELL3 - no mid nodes
153 { 0, 1, 0, 0 }, // TRI6 - mid nodes on edges
154 { 0, 1, 1, 0 }, // TRI7 - mid nodes on edges and faces
155 { 0, 0, 0, 0 }, // QUAD - no mid nodes
156 { 0, 0, 0, 0 }, // QUAD4 - no mid nodes
157 { 0, 0, 1, 0 }, // QUAD5 - mid node on faces
158 { 0, 1, 0, 0 }, // QUAD8 - mid nodes on edges
159 { 0, 1, 1, 0 }, // QUAD9 - mid nodes on edges and faces
160 { 0, 0, 0, 0 }, // SHELL - no mid nodes
161 { 0, 0, 0, 0 }, // SHELL4 - no mid nodes
162 { 0, 0, 1, 0 }, // SHELL5 - mid node on faces
163 { 0, 1, 0, 0 }, // SHELL8 - mid nodes on edges
164 { 0, 1, 1, 0 }, // SHELL9 - mid nodes on edges and faces
165 { 0, 0, 0, 0 }, // TETRA - no mid nodes
166 { 0, 0, 0, 0 }, // TETRA4 - no mid nodes
167 { 0, 0, 0, 0 }, // TET4 - no mid nodes
168 { 0, 0, 1, 0 }, // TETRA8 - mid nodes on faces
169 { 0, 1, 0, 0 }, // TETRA10 - mid nodes on edges
170 { 0, 1, 1, 0 }, // TETRA14 - mid nodes on edges and faces
171 { 0, 0, 0, 0 }, // PYRAMID - no mid nodes
172 { 0, 0, 0, 0 }, // PYRAMID5 - no mid nodes
173 { 0, 0, 1, 0 }, // PYRAMID10 - *** TODO - not sure if this is right...
174 { 0, 1, 0, 0 }, // PYRAMID13 - *** TODO - not sure if this is right...
175 { 0, 1, 1, 0 }, // PYRAMID18 - *** TODO - not sure if this is right...
176 { 0, 0, 0, 0 }, // WEDGE - no mid nodes
177 { 0, 0, 0, 0 }, // KNIFE - no mid nodes
178 { 0, 0, 0, 0 }, // HEX - no mid nodes
179 { 0, 0, 0, 0 }, // HEX8 - no mid nodes
180 { 0, 0, 0, 1 }, // HEX9 - mid node on element
181 { 0, 1, 0, 0 }, // HEX20 - mid nodes on edges
182 { 0, 1, 1, 1 }, // HEX27 - mid node on edges, faces and element
183 { 0, 0, 0, 0 }, // HEXSHELL - *** TODO - not sure if this is right...
184 { 0, 0, 0, 0 }, // POLYGON
185 { 0, 0, 0, 0 }, // POLYHEDRON
186 { 0, 0, 0, 0 } // UNKNOWN - no mid nodes
187 };
188
189 const int ExoIIUtil::ElementGeometricDimension[] = {
190 3, // SPHERE
191 3, // SPRING
192 2, 2,
193 2, // BAR
194 3, 3,
195 3, // BEAM
196 3, 3,
197 3, // TRUSS
198 3, 3, 3, 3,
199 3, // TRI
200 2, 2, 2, 2,
201 2, // QUAD
202 3, 3, 3, 3,
203 3, // SHELL
204 3, 3, 3, 3,
205 3, // TETRA
206 3, 3, 3, 3, 3,
207 3, // PYRAMID
208 3, // WEDGE
209 3, // KNIFE
210 3, 3, 3, 3,
211 3, // HEX
212 3, // HEXSHELL
213 2, // POLYGON
214 3, // POLYHEDRON
215 0 // UNKNOWN
216 };
217
218 ExoIIElementType ExoIIUtil::static_element_name_to_type( const char* name )
219 {
220 int i;
221 for( i = 0; i < EXOII_MAX_ELEM_TYPE; i++ )
222 if( strcmp( ElementTypeNames[i], name ) == 0 ) return (ExoIIElementType)i;
223
224 return EXOII_MAX_ELEM_TYPE;
225 }
226
227 ExoIIElementType ExoIIUtil::static_get_element_type( Interface* mdbImpl,
228 const EntityHandle entity,
229 const Tag mid_nodes_tag,
230 const Tag geom_dimension_tag,
231 const EntityType indiv_entity_type )
232 {
233 // branch based on what kind of entity we're looking at
234 EntityType handle_type = mdbImpl->type_from_handle( entity );
235
236 if( handle_type == MBENTITYSET )
237 {
238
239 // it's a meshset - assume it's a block (check this?) and work off the midnodes tag
240
241 // get the element type of the block; first, get the hasMidNodes tag, then convert to an exo
242 // element type
243 int has_mid_nodes[4];
244 int dimension = -1;
245 if( mdbImpl->tag_get_data( mid_nodes_tag, &entity, 1, has_mid_nodes ) != MB_SUCCESS )
246 {
247 // no mid nodes tag - look for indiv entity type, and if it was input, output the
248 // default number of vertices
249 if( MBMAXTYPE != indiv_entity_type )
250 {
251 // get dimension
252 if( indiv_entity_type == MBQUAD || indiv_entity_type == MBTRI )
253 dimension = 3; // want to ouput shells by default
254 else if( indiv_entity_type == MBEDGE )
255 dimension = 2;
256 else
257 dimension = CN::Dimension( indiv_entity_type );
258
259 return get_element_type_from_num_verts( CN::VerticesPerEntity( indiv_entity_type ), indiv_entity_type,
260 dimension );
261 }
262 else
263 return EXOII_MAX_ELEM_TYPE;
264 }
265 else
266 {
267 // block meshset had midnodes tag - look for geometric dimension one too
268 mdbImpl->tag_get_data( geom_dimension_tag, &entity, 1, &dimension );
269 }
270
271 for( int i = 0; i < EXOII_MAX_ELEM_TYPE; i++ )
272 {
273 if( ( indiv_entity_type == MBMAXTYPE || indiv_entity_type == ExoIIElementMBEntity[i] ) &&
274 has_mid_nodes[0] == HasMidNodes[i][0] && has_mid_nodes[1] == HasMidNodes[i][1] &&
275 has_mid_nodes[2] == HasMidNodes[i][2] && has_mid_nodes[3] == HasMidNodes[i][3] &&
276 ( -1 == dimension || ElementGeometricDimension[i] == dimension ) )
277 return (ExoIIElementType)i;
278 }
279
280 return EXOII_MAX_ELEM_TYPE;
281 }
282
283 else if( handle_type == MBVERTEX )
284 // only have one type of entity for vertices...
285 return EXOII_SPHERE;
286
287 else
288 {
289 std::vector< EntityHandle > tmp( 31 );
290
291 mdbImpl->get_connectivity( &entity, 1, tmp, true );
292 return get_element_type_from_num_verts( tmp.size(), indiv_entity_type );
293 // it's a regular entity - look for a connectivity tag
294 }
295
296 // if we've gotten here, we failed
297 // return EXOII_MAX_ELEM_TYPE;
298 }
299
300 ExoIIElementType ExoIIUtil::get_element_type_from_num_verts( const int num_verts,
301 const EntityType entity_type,
302 const int dimension )
303 {
304 if( MBPOLYGON == entity_type && 2 == dimension ) return EXOII_POLYGON;
305 if( MBPOLYHEDRON == entity_type && 3 == dimension ) return EXOII_POLYHEDRON;
306 for( int i = 0; i < EXOII_MAX_ELEM_TYPE; i++ )
307 {
308 if( ( entity_type == MBMAXTYPE || entity_type == ExoIIElementMBEntity[i] ) &&
309 VerticesPerElement[i] == num_verts && ElementGeometricDimension[i] >= dimension )
310 return (ExoIIElementType)i;
311 }
312
313 return EXOII_MAX_ELEM_TYPE;
314 }
315
316 } // namespace moab