Branch data Line data Source code
1 : : /* *****************************************************************
2 : : MESQUITE -- The Mesh Quality Improvement Toolkit
3 : :
4 : : Copyright 2004 Lawrence Livermore National Laboratory. Under
5 : : the terms of Contract B545069 with the University of Wisconsin --
6 : : Madison, Lawrence Livermore National Laboratory retains certain
7 : : 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 : : This library is distributed in the hope that it will be useful,
15 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : Lesser General Public License for more details.
18 : :
19 : : You should have received a copy of the GNU Lesser General Public License
20 : : (lgpl.txt) along with this library; if not, write to the Free Software
21 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 : :
23 : : [email protected]
24 : :
25 : : ***************************************************************** */
26 : :
27 : : #include "MsqError.hpp"
28 : : #include "TopologyInfo.hpp"
29 : :
30 : : #include <string.h>
31 : : #include <assert.h>
32 : :
33 : : namespace MBMesquite
34 : : {
35 : :
36 : 32 : TopologyInfo TopologyInfo::instance;
37 : :
38 : : const char long_polygon_name[] = "Polygon";
39 : : const char long_triangle_name[] = "Triangle";
40 : : const char long_quadrilateral_name[] = "Quadrilateral";
41 : : const char long_polyhedron_name[] = "Polyhedron";
42 : : const char long_tetrahedron_name[] = "Tetrahedron";
43 : : const char long_hexahedron_name[] = "Hexahedron";
44 : : const char long_prism_name[] = "Prism";
45 : : const char long_pyramid_name[] = "Pyramd";
46 : : const char long_septahedron_name[] = "Septahedron";
47 : : const char short_polygon_name[] = "Polygon";
48 : : const char short_triangle_name[] = "Tri";
49 : : const char short_quadrilateral_name[] = "Quad";
50 : : const char short_polyhedron_name[] = "Polyhedron";
51 : : const char short_tetrahedron_name[] = "Tet";
52 : : const char short_hexahedron_name[] = "Hex";
53 : : const char short_prism_name[] = "Pri";
54 : : const char short_pyramid_name[] = "Pyr";
55 : : const char short_septahedron_name[] = "Sept";
56 : :
57 : 32 : TopologyInfo::TopologyInfo()
58 : : {
59 : 32 : memset( dimMap, 0, sizeof( dimMap ) );
60 : 32 : memset( adjMap, 0, sizeof( adjMap ) );
61 : 32 : memset( edgeMap, 0, sizeof( edgeMap ) );
62 : 32 : memset( faceMap, 0, sizeof( faceMap ) );
63 : 32 : memset( vertAdjMap, 0, sizeof( vertAdjMap ) );
64 : 32 : memset( shortNames, 0, sizeof( shortNames ) );
65 : 32 : memset( longNames, 0, sizeof( longNames ) );
66 : :
67 : 32 : longNames[POLYGON] = long_polygon_name;
68 : 32 : longNames[TRIANGLE] = long_triangle_name;
69 : 32 : longNames[QUADRILATERAL] = long_quadrilateral_name;
70 : 32 : longNames[POLYHEDRON] = long_polyhedron_name;
71 : 32 : longNames[TETRAHEDRON] = long_tetrahedron_name;
72 : 32 : longNames[HEXAHEDRON] = long_hexahedron_name;
73 : 32 : longNames[PRISM] = long_prism_name;
74 : 32 : longNames[PYRAMID] = long_pyramid_name;
75 : 32 : longNames[SEPTAHEDRON] = long_septahedron_name;
76 : :
77 : 32 : shortNames[POLYGON] = short_polygon_name;
78 : 32 : shortNames[TRIANGLE] = short_triangle_name;
79 : 32 : shortNames[QUADRILATERAL] = short_quadrilateral_name;
80 : 32 : shortNames[POLYHEDRON] = short_polyhedron_name;
81 : 32 : shortNames[TETRAHEDRON] = short_tetrahedron_name;
82 : 32 : shortNames[HEXAHEDRON] = short_hexahedron_name;
83 : 32 : shortNames[PRISM] = short_prism_name;
84 : 32 : shortNames[PYRAMID] = short_pyramid_name;
85 : 32 : shortNames[SEPTAHEDRON] = short_septahedron_name;
86 : :
87 : 32 : dimMap[POLYGON] = 2;
88 : 32 : dimMap[TRIANGLE] = 2;
89 : 32 : dimMap[QUADRILATERAL] = 2;
90 : 32 : dimMap[POLYHEDRON] = 3;
91 : 32 : dimMap[TETRAHEDRON] = 3;
92 : 32 : dimMap[HEXAHEDRON] = 3;
93 : 32 : dimMap[PRISM] = 3;
94 : 32 : dimMap[PYRAMID] = 3;
95 : 32 : dimMap[SEPTAHEDRON] = 3;
96 : :
97 : 32 : adjMap[TRIANGLE][0] = 3;
98 : 32 : adjMap[TRIANGLE][1] = 3;
99 : 32 : adjMap[TRIANGLE][2] = 1;
100 : 32 : adjMap[TRIANGLE][3] = 0;
101 : :
102 : 32 : adjMap[QUADRILATERAL][0] = 4;
103 : 32 : adjMap[QUADRILATERAL][1] = 4;
104 : 32 : adjMap[QUADRILATERAL][2] = 1;
105 : 32 : adjMap[QUADRILATERAL][3] = 0;
106 : :
107 : 32 : adjMap[TETRAHEDRON][0] = 4;
108 : 32 : adjMap[TETRAHEDRON][1] = 6;
109 : 32 : adjMap[TETRAHEDRON][2] = 4;
110 : 32 : adjMap[TETRAHEDRON][3] = 1;
111 : :
112 : 32 : adjMap[HEXAHEDRON][0] = 8;
113 : 32 : adjMap[HEXAHEDRON][1] = 12;
114 : 32 : adjMap[HEXAHEDRON][2] = 6;
115 : 32 : adjMap[HEXAHEDRON][3] = 1;
116 : :
117 : 32 : adjMap[PRISM][0] = 6;
118 : 32 : adjMap[PRISM][1] = 9;
119 : 32 : adjMap[PRISM][2] = 5;
120 : 32 : adjMap[PRISM][3] = 1;
121 : :
122 : 32 : adjMap[PYRAMID][0] = 5;
123 : 32 : adjMap[PYRAMID][1] = 8;
124 : 32 : adjMap[PYRAMID][2] = 5;
125 : 32 : adjMap[PYRAMID][3] = 1;
126 : :
127 : 32 : adjMap[SEPTAHEDRON][0] = 7;
128 : 32 : adjMap[SEPTAHEDRON][1] = 11;
129 : 32 : adjMap[SEPTAHEDRON][2] = 6; /* See description in TSTT mesh interface doc */
130 : 32 : adjMap[SEPTAHEDRON][3] = 1;
131 : :
132 : : int side;
133 [ + + ]: 128 : for( side = 0; side < 3; ++side )
134 : : {
135 : 96 : edgeMap[TRIANGLE - FIRST_FACE][side][0] = side;
136 : 96 : edgeMap[TRIANGLE - FIRST_FACE][side][1] = ( side + 1 ) % 3;
137 : : }
138 [ + + ]: 160 : for( side = 0; side < 4; ++side )
139 : : {
140 : 128 : edgeMap[QUADRILATERAL - FIRST_FACE][side][0] = side;
141 : 128 : edgeMap[QUADRILATERAL - FIRST_FACE][side][1] = ( side + 1 ) % 4;
142 : : }
143 [ + + ]: 128 : for( side = 0; side < 3; ++side )
144 : : {
145 : 96 : edgeMap[TETRAHEDRON - FIRST_FACE][side][0] = side;
146 : 96 : edgeMap[TETRAHEDRON - FIRST_FACE][side][1] = ( side + 1 ) % 3;
147 : : }
148 [ + + ]: 128 : for( side = 3; side < 6; ++side )
149 : : {
150 : 96 : edgeMap[TETRAHEDRON - FIRST_FACE][side][0] = side - 3;
151 : 96 : edgeMap[TETRAHEDRON - FIRST_FACE][side][1] = 3;
152 : : }
153 [ + + ]: 160 : for( side = 0; side < 4; ++side )
154 : : {
155 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][0] = side;
156 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][1] = ( side + 1 ) % 4;
157 : : }
158 [ + + ]: 160 : for( side = 4; side < 8; ++side )
159 : : {
160 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][0] = side - 4;
161 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][1] = side;
162 : : }
163 [ + + ]: 160 : for( side = 8; side < 12; ++side )
164 : : {
165 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][0] = side - 4;
166 : 128 : edgeMap[HEXAHEDRON - FIRST_FACE][side][1] = 4 + ( side + 1 ) % 4;
167 : : }
168 [ + + ]: 128 : for( side = 0; side < 3; ++side )
169 : : {
170 : 96 : edgeMap[PRISM - FIRST_FACE][side][0] = side;
171 : 96 : edgeMap[PRISM - FIRST_FACE][side][1] = ( side + 1 ) % 3;
172 : : }
173 [ + + ]: 128 : for( side = 3; side < 6; ++side )
174 : : {
175 : 96 : edgeMap[PRISM - FIRST_FACE][side][0] = side - 3;
176 : 96 : edgeMap[PRISM - FIRST_FACE][side][1] = side;
177 : : }
178 [ + + ]: 128 : for( side = 6; side < 9; ++side )
179 : : {
180 : 96 : edgeMap[PRISM - FIRST_FACE][side][0] = side - 3;
181 : 96 : edgeMap[PRISM - FIRST_FACE][side][1] = 3 + ( side + 1 ) % 3;
182 : : }
183 [ + + ]: 160 : for( side = 0; side < 4; ++side )
184 : : {
185 : 128 : edgeMap[PYRAMID - FIRST_FACE][side][0] = side;
186 : 128 : edgeMap[PYRAMID - FIRST_FACE][side][1] = ( side + 1 ) % 4;
187 : : }
188 [ + + ]: 160 : for( side = 4; side < 8; ++side )
189 : : {
190 : 128 : edgeMap[PYRAMID - FIRST_FACE][side][0] = side - 4;
191 : 128 : edgeMap[PYRAMID - FIRST_FACE][side][1] = 4;
192 : : }
193 : :
194 [ + + ]: 128 : for( side = 0; side < 3; ++side )
195 : : {
196 : 96 : faceMap[TETRAHEDRON - FIRST_VOL][side][0] = 3;
197 : 96 : faceMap[TETRAHEDRON - FIRST_VOL][side][1] = side;
198 : 96 : faceMap[TETRAHEDRON - FIRST_VOL][side][2] = ( side + 1 ) % 3;
199 : 96 : faceMap[TETRAHEDRON - FIRST_VOL][side][3] = 3;
200 : : }
201 : 32 : faceMap[TETRAHEDRON - FIRST_VOL][3][0] = 3;
202 : 32 : faceMap[TETRAHEDRON - FIRST_VOL][3][1] = 2;
203 : 32 : faceMap[TETRAHEDRON - FIRST_VOL][3][2] = 1;
204 : 32 : faceMap[TETRAHEDRON - FIRST_VOL][3][3] = 0;
205 : :
206 [ + + ]: 160 : for( side = 0; side < 4; ++side )
207 : : {
208 : 128 : faceMap[HEXAHEDRON - FIRST_VOL][side][0] = 4;
209 : 128 : faceMap[HEXAHEDRON - FIRST_VOL][side][1] = side;
210 : 128 : faceMap[HEXAHEDRON - FIRST_VOL][side][2] = ( side + 1 ) % 4;
211 : 128 : faceMap[HEXAHEDRON - FIRST_VOL][side][3] = 4 + ( side + 1 ) % 4;
212 : 128 : faceMap[HEXAHEDRON - FIRST_VOL][side][4] = side + 4;
213 : : }
214 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][4][0] = 4;
215 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][4][1] = 3;
216 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][4][2] = 2;
217 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][4][3] = 1;
218 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][4][4] = 0;
219 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][5][0] = 4;
220 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][5][1] = 4;
221 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][5][2] = 5;
222 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][5][3] = 6;
223 : 32 : faceMap[HEXAHEDRON - FIRST_VOL][5][4] = 7;
224 : :
225 [ + + ]: 160 : for( side = 0; side < 4; ++side )
226 : : {
227 : 128 : faceMap[PYRAMID - FIRST_VOL][side][0] = 3;
228 : 128 : faceMap[PYRAMID - FIRST_VOL][side][1] = side;
229 : 128 : faceMap[PYRAMID - FIRST_VOL][side][2] = ( side + 1 ) % 4;
230 : 128 : faceMap[PYRAMID - FIRST_VOL][side][3] = 4;
231 : : }
232 : 32 : faceMap[PYRAMID - FIRST_VOL][4][0] = 4;
233 : 32 : faceMap[PYRAMID - FIRST_VOL][4][1] = 3;
234 : 32 : faceMap[PYRAMID - FIRST_VOL][4][2] = 2;
235 : 32 : faceMap[PYRAMID - FIRST_VOL][4][3] = 1;
236 : 32 : faceMap[PYRAMID - FIRST_VOL][4][4] = 0;
237 : :
238 [ + + ]: 128 : for( side = 0; side < 3; ++side )
239 : : {
240 : 96 : faceMap[PRISM - FIRST_VOL][side][0] = 4;
241 : 96 : faceMap[PRISM - FIRST_VOL][side][1] = side;
242 : 96 : faceMap[PRISM - FIRST_VOL][side][2] = ( side + 1 ) % 3;
243 : 96 : faceMap[PRISM - FIRST_VOL][side][3] = 3 + ( side + 1 ) % 3;
244 : 96 : faceMap[PRISM - FIRST_VOL][side][4] = side + 3;
245 : : }
246 : 32 : faceMap[PRISM - FIRST_VOL][3][0] = 3;
247 : 32 : faceMap[PRISM - FIRST_VOL][3][1] = 2;
248 : 32 : faceMap[PRISM - FIRST_VOL][3][2] = 1;
249 : 32 : faceMap[PRISM - FIRST_VOL][3][3] = 0;
250 : 32 : faceMap[PRISM - FIRST_VOL][4][0] = 3;
251 : 32 : faceMap[PRISM - FIRST_VOL][4][1] = 3;
252 : 32 : faceMap[PRISM - FIRST_VOL][4][2] = 4;
253 : 32 : faceMap[PRISM - FIRST_VOL][4][3] = 5;
254 : :
255 : : int i;
256 [ + + ]: 128 : for( i = 0; i < 3; ++i )
257 : : {
258 : 96 : vertAdjMap[TRIANGLE - FIRST_FACE][i][0] = 2;
259 : 96 : vertAdjMap[TRIANGLE - FIRST_FACE][i][1] = ( i + 1 ) % 3;
260 : 96 : vertAdjMap[TRIANGLE - FIRST_FACE][i][2] = ( i + 2 ) % 3;
261 : : }
262 : :
263 [ + + ]: 160 : for( i = 0; i < 4; ++i )
264 : : {
265 : 128 : vertAdjMap[QUADRILATERAL - FIRST_FACE][i][0] = 2;
266 : 128 : vertAdjMap[QUADRILATERAL - FIRST_FACE][i][1] = ( i + 1 ) % 4;
267 : 128 : vertAdjMap[QUADRILATERAL - FIRST_FACE][i][2] = ( i + 3 ) % 4;
268 : : }
269 : :
270 : 32 : unsigned tet_corner_data[] = { 1, 2, 3, 0, 3, 2, 3, 0, 1, 2, 1, 0 };
271 [ + + ]: 160 : for( i = 0; i < 4; ++i )
272 : : {
273 : 128 : vertAdjMap[TETRAHEDRON - FIRST_FACE][i][0] = 3;
274 [ + + ]: 512 : for( unsigned j = 0; j < 3; ++j )
275 : 384 : vertAdjMap[TETRAHEDRON - FIRST_FACE][i][j + 1] = tet_corner_data[3 * i + j];
276 : : }
277 : :
278 [ + + ]: 160 : for( i = 0; i < 4; ++i )
279 : : {
280 : 128 : vertAdjMap[PYRAMID - FIRST_FACE][i][0] = 3;
281 : 128 : vertAdjMap[PYRAMID - FIRST_FACE][i][1] = ( i + 1 ) % 4;
282 : 128 : vertAdjMap[PYRAMID - FIRST_FACE][i][2] = ( i + 3 ) % 4;
283 : 128 : vertAdjMap[PYRAMID - FIRST_FACE][i][3] = 4;
284 : : }
285 : 32 : vertAdjMap[PYRAMID - FIRST_FACE][4][0] = 4;
286 [ + + ]: 160 : for( i = 0; i < 4; i++ )
287 : 128 : vertAdjMap[PYRAMID - FIRST_FACE][4][i + 1] = 3 - i;
288 : :
289 [ + + ]: 160 : for( i = 0; i < 4; ++i )
290 : : {
291 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][0] = 3;
292 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][1] = ( i + 1 ) % 4;
293 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][2] = ( i + 3 ) % 4;
294 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][3] = i + 4;
295 : : }
296 [ + + ]: 160 : for( i = 4; i < 8; ++i )
297 : : {
298 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][0] = 3;
299 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][1] = ( i + 3 ) % 4 + 4;
300 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][2] = ( i + 1 ) % 4 + 4;
301 : 128 : vertAdjMap[HEXAHEDRON - FIRST_FACE][i][3] = i - 4;
302 : : }
303 : :
304 [ + + ]: 128 : for( i = 0; i < 3; ++i )
305 : : {
306 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][0] = 3;
307 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][1] = ( i + 1 ) % 3;
308 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][2] = ( i + 2 ) % 3;
309 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][3] = i + 3;
310 : : }
311 [ + + ]: 128 : for( i = 3; i < 6; ++i )
312 : : {
313 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][0] = 3;
314 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][1] = ( i + 2 ) % 3 + 3;
315 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][2] = ( i + 1 ) % 3 + 3;
316 : 96 : vertAdjMap[PRISM - FIRST_FACE][i][3] = i - 3;
317 : : }
318 : :
319 : : // Build reverse vertex-vertex adjacency index map
320 : 32 : const EntityTopology types[] = { TRIANGLE, QUADRILATERAL, TETRAHEDRON, PYRAMID, PRISM, HEXAHEDRON };
321 : 32 : const int num_types = sizeof( types ) / sizeof( types[0] );
322 [ + + ]: 224 : for( i = 0; i < num_types; ++i )
323 : : {
324 [ + - ]: 192 : const unsigned num_vert = corners( types[i] );
325 [ + + ]: 1152 : for( unsigned v = 0; v < num_vert; ++v )
326 : : {
327 : : unsigned num_v_adj;
328 [ + - ]: 960 : const unsigned* v_adj = adjacent_vertices( types[i], v, num_v_adj );
329 : 960 : unsigned* reverse = revVertAdjIdx[types[i] - FIRST_FACE][v];
330 : 960 : reverse[0] = num_v_adj;
331 : :
332 [ + + ]: 3648 : for( unsigned j = 0; j < num_v_adj; ++j )
333 : : {
334 : : unsigned num_j_adj, k;
335 [ + - ]: 2688 : const unsigned* j_adj = adjacent_vertices( types[i], v_adj[j], num_j_adj );
336 [ + - ][ + + ]: 5216 : for( k = 0; k < num_j_adj && j_adj[k] != v; ++k )
337 : : ;
338 [ - + ]: 2688 : assert( k < num_j_adj ); // If this fails, vertAdjMap is corrupt!
339 : 2688 : reverse[j + 1] = k;
340 : : }
341 : : }
342 : : }
343 : 32 : }
344 : :
345 : 33339983 : void TopologyInfo::higher_order( EntityTopology topo, unsigned num_nodes, bool& midedge, bool& midface, bool& midvol,
346 : : MsqError& err )
347 : : {
348 : 33339983 : int ho = higher_order( topo, num_nodes, err );
349 : 33339983 : midedge = (bool)( ( ho & ( 1 << 1 ) ) >> 1 );
350 : 33339983 : midface = (bool)( ( ho & ( 1 << 2 ) ) >> 2 );
351 : 33339983 : midvol = (bool)( ( ho & ( 1 << 3 ) ) >> 3 );
352 : 33339983 : }
353 : :
354 : 33339983 : int TopologyInfo::higher_order( EntityTopology topo, unsigned num_nodes, MsqError& err )
355 : : {
356 : 33339983 : int result = 0;
357 [ - + ]: 33339983 : if( topo == POLYGON ) // polygons currently do not have higher order elements
358 : 0 : return 0;
359 : :
360 [ + - ][ - + ]: 33339983 : if( topo >= MIXED || num_nodes < instance.adjMap[topo][0] )
361 : : {
362 [ # # ]: 0 : MSQ_SETERR( err )( "Invalid element topology", MsqError::INVALID_ARG );
363 : 0 : return 0;
364 : : }
365 : :
366 : 33339983 : unsigned dim = instance.dimMap[topo];
367 [ - + ]: 33339983 : assert( num_nodes >= instance.adjMap[topo][0] );
368 : 33339983 : unsigned nodes = num_nodes - instance.adjMap[topo][0];
369 : 33339983 : unsigned edges = instance.adjMap[topo][1];
370 : 33339983 : unsigned faces = instance.adjMap[topo][2];
371 [ + - ][ + + ]: 33339983 : if( edges && nodes >= edges )
372 : : {
373 : 171996 : nodes -= edges;
374 : 171996 : result |= 1 << 1;
375 : : }
376 [ + - ][ + + ]: 33339983 : if( faces && nodes >= faces )
377 : : {
378 : 16672 : nodes -= faces;
379 : 16672 : result |= 1 << 2;
380 : : }
381 [ - + ]: 33339983 : if( 1 == nodes )
382 : : {
383 [ # # ]: 0 : if( 2 == dim )
384 : : {
385 : 0 : nodes -= 1;
386 : 0 : result |= 1 << 2;
387 : : }
388 [ # # ]: 0 : else if( 3 == dim )
389 : : {
390 : 0 : nodes -= 1;
391 : 0 : result |= 1 << 3;
392 : : }
393 : : }
394 : :
395 [ - + ][ # # ]: 33339983 : if( nodes ) { MSQ_SETERR( err )( "Invalid element topology", MsqError::INVALID_STATE ); }
396 : :
397 : 33339983 : return result;
398 : : }
399 : :
400 : 368971 : int TopologyInfo::higher_order_from_side( EntityTopology topo, unsigned num_nodes, unsigned side_dimension,
401 : : unsigned side_number, MsqError& err )
402 : : {
403 : 368971 : bool mids[4] = { true };
404 [ + - ]: 368971 : higher_order( topo, num_nodes, mids[1], mids[2], mids[3], err );
405 [ + - ][ - + ]: 368971 : MSQ_ERRZERO( err );
[ # # ][ # # ]
[ - + ]
406 : :
407 [ + - ][ + - ]: 368971 : if( side_dimension > dimension( topo ) || side_number > adjacent( topo, side_dimension ) )
[ + - ][ - + ]
[ - + ]
408 : : {
409 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "Invalid side number: %u\n", side_number );
410 : 0 : return 0;
411 : : }
412 : :
413 [ + + ]: 368971 : if( !mids[side_dimension] ) return -1;
414 : :
415 : 33686 : int result = side_number;
416 [ - - + - : 33686 : switch( side_dimension )
- ]
417 : : {
418 : : case 3:
419 [ # # ][ # # ]: 0 : if( mids[2] ) result += faces( topo );
420 : : case 2:
421 [ # # ][ # # ]: 0 : if( mids[1] ) result += edges( topo );
422 : : case 1:
423 [ + - ]: 33686 : result += corners( topo );
424 : : case 0:
425 : 33686 : break;
426 : : default:
427 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "Invalid dimension: %u\n", side_dimension );
428 : 0 : return 0;
429 : : }
430 : 368971 : return result;
431 : : }
432 : :
433 : 4894 : void TopologyInfo::side_from_higher_order( EntityTopology topo, unsigned num_nodes, unsigned node_number,
434 : : unsigned& side_dim_out, unsigned& side_num_out, MsqError& err )
435 : : {
436 : : bool midedge, midface, midvol;
437 [ + - ][ + - ]: 9788 : higher_order( topo, num_nodes, midedge, midface, midvol, err );MSQ_ERRRTN( err );
[ - + ][ # # ]
[ # # ][ - + ]
438 : 4894 : side_num_out = node_number;
439 : :
440 [ + - ][ - + ]: 4894 : if( side_num_out < corners( topo ) )
441 : : {
442 : 0 : side_dim_out = 0;
443 : 0 : return;
444 : : }
445 [ + - ]: 4894 : side_num_out -= corners( topo );
446 : :
447 [ + - ]: 4894 : if( midedge )
448 : : {
449 [ + - ][ + - ]: 4894 : if( side_num_out < edges( topo ) )
450 : : {
451 : 4894 : side_dim_out = 1;
452 : 4894 : return;
453 : : }
454 [ # # ]: 0 : side_num_out -= edges( topo );
455 : : }
456 : :
457 [ # # ]: 0 : if( midface )
458 : : {
459 [ # # ][ # # ]: 0 : if( side_num_out < faces( topo ) )
460 : : {
461 : 0 : side_dim_out = 2;
462 : 0 : return;
463 : : }
464 [ # # ]: 0 : side_num_out -= faces( topo );
465 : : }
466 : :
467 [ # # ][ # # ]: 0 : if( midvol && side_num_out == 0 )
468 : : {
469 : 0 : side_dim_out = 3;
470 : 0 : return;
471 : : }
472 : :
473 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "Invalid node index\n" );
474 : : }
475 : :
476 : 1403687 : const unsigned* TopologyInfo::edge_vertices( EntityTopology topo, unsigned edge, MsqError& err )
477 : : {
478 [ + - ][ + - ]: 1403687 : if( topo < (EntityTopology)FIRST_FACE || topo > (EntityTopology)LAST_VOL || edge >= edges( topo ) )
[ - + ][ - + ]
479 : : {
480 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG );
481 : 0 : topo = (EntityTopology)FIRST_FACE;
482 : 0 : edge = 0;
483 : : }
484 : :
485 : 1403687 : return instance.edgeMap[topo - FIRST_FACE][edge];
486 : : }
487 : :
488 : 953285 : const unsigned* TopologyInfo::edge_vertices( EntityTopology topo, unsigned edge )
489 : : {
490 [ + - ][ + - ]: 953285 : if( topo < (EntityTopology)FIRST_FACE || topo > (EntityTopology)LAST_VOL || edge >= edges( topo ) ) { return 0; }
[ - + ][ - + ]
491 : 953285 : return instance.edgeMap[topo - FIRST_FACE][edge];
492 : : }
493 : :
494 : 0 : const unsigned* TopologyInfo::face_vertices( EntityTopology topo, unsigned face, unsigned& length, MsqError& err )
495 : : {
496 [ # # ][ # # ]: 0 : if( topo < (EntityTopology)FIRST_VOL || topo > (EntityTopology)LAST_VOL || face >= faces( topo ) )
[ # # ][ # # ]
497 : : {
498 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG );
499 : 0 : topo = (EntityTopology)FIRST_VOL;
500 : 0 : face = 0;
501 : : }
502 : :
503 : 0 : length = instance.faceMap[topo - FIRST_VOL][face][0];
504 : 0 : return instance.faceMap[topo - FIRST_VOL][face] + 1;
505 : : }
506 : 0 : const unsigned* TopologyInfo::face_vertices( EntityTopology topo, unsigned face, unsigned& length )
507 : : {
508 [ # # ][ # # ]: 0 : if( topo < (EntityTopology)FIRST_VOL || topo > (EntityTopology)LAST_VOL || face >= faces( topo ) ) { return 0; }
[ # # ][ # # ]
509 : :
510 : 0 : length = instance.faceMap[topo - FIRST_VOL][face][0];
511 : 0 : return instance.faceMap[topo - FIRST_VOL][face] + 1;
512 : : }
513 : :
514 : 239 : const unsigned* TopologyInfo::side_vertices( EntityTopology topo, unsigned dim, unsigned side, unsigned& count_out,
515 : : MsqError& err )
516 : : {
517 : : static const unsigned all[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
518 : : const unsigned* result;
519 : :
520 [ + - ][ - + ]: 239 : if( dim != 0 && dim == dimension( topo ) )
[ - + ]
521 : : {
522 : 0 : count_out = corners( topo );
523 : 0 : result = all;
524 : : }
525 [ + - ]: 239 : else if( dim == 1 )
526 : : {
527 : 239 : count_out = 2;
528 : 239 : result = edge_vertices( topo, side, err );
529 : : }
530 [ # # ]: 0 : else if( dim == 2 )
531 : : {
532 : 0 : result = face_vertices( topo, side, count_out, err );
533 : : }
534 : : else
535 : : {
536 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG );
537 : 0 : count_out = 0;
538 : 0 : result = 0;
539 : : }
540 : 239 : return result;
541 : : }
542 : 0 : const unsigned* TopologyInfo::side_vertices( EntityTopology topo, unsigned dim, unsigned side, unsigned& count_out )
543 : : {
544 : : static const unsigned all[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
545 : : const unsigned* result;
546 : :
547 [ # # ][ # # ]: 0 : if( dim != 0 && dim == dimension( topo ) )
[ # # ]
548 : : {
549 : 0 : count_out = corners( topo );
550 : 0 : result = all;
551 : : }
552 [ # # ]: 0 : else if( dim == 1 )
553 : : {
554 : 0 : count_out = 2;
555 : 0 : result = edge_vertices( topo, side );
556 : : }
557 [ # # ]: 0 : else if( dim == 2 )
558 : : {
559 : 0 : result = face_vertices( topo, side, count_out );
560 : : }
561 : : else
562 : : {
563 : 0 : result = 0;
564 : : }
565 : 0 : return result;
566 : : }
567 : :
568 : 0 : void TopologyInfo::side_number( EntityTopology topo, unsigned num_nodes, unsigned node_index, unsigned& side_dim_out,
569 : : unsigned& side_num_out, MsqError& err )
570 : : {
571 [ # # ][ # # ]: 0 : if( topo >= (EntityTopology)MIXED || num_nodes < instance.adjMap[topo][0] )
572 : : {
573 [ # # ]: 0 : MSQ_SETERR( err )( "Invalid element topology", MsqError::INVALID_ARG );
574 : 0 : return;
575 : : }
576 : :
577 : 0 : unsigned nodes = instance.adjMap[topo][0];
578 : 0 : unsigned edges = instance.adjMap[topo][1];
579 : 0 : unsigned faces = instance.adjMap[topo][2];
580 : 0 : side_num_out = node_index;
581 : :
582 [ # # ]: 0 : if( side_num_out < nodes )
583 : : {
584 : 0 : side_dim_out = 0;
585 : 0 : return;
586 : : }
587 : 0 : num_nodes -= nodes;
588 : 0 : side_num_out -= nodes;
589 : :
590 [ # # ][ # # ]: 0 : if( edges && num_nodes >= edges )
591 : : {
592 [ # # ]: 0 : if( side_num_out < edges )
593 : : {
594 : 0 : side_dim_out = 1;
595 : 0 : return;
596 : : }
597 : 0 : num_nodes -= edges;
598 : 0 : side_num_out -= edges;
599 : : }
600 [ # # ][ # # ]: 0 : if( faces && num_nodes >= faces )
601 : : {
602 [ # # ]: 0 : if( side_num_out < faces )
603 : : {
604 : 0 : side_dim_out = 2;
605 : 0 : return;
606 : : }
607 : 0 : num_nodes -= faces;
608 : 0 : side_num_out -= faces;
609 : : }
610 [ # # ]: 0 : if( side_num_out == 0 )
611 : : {
612 : 0 : side_dim_out = instance.dimMap[topo];
613 : 0 : side_num_out = 0;
614 : 0 : return;
615 : : }
616 : :
617 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG );
618 : : }
619 : :
620 : 14094482 : const unsigned* TopologyInfo::adjacent_vertices( EntityTopology topo, unsigned index, unsigned& num_adj_out )
621 : : {
622 : 14094482 : const unsigned count = corners( topo );
623 [ + - ][ - + ]: 14094482 : if( !count || index >= count )
624 : : {
625 : 0 : num_adj_out = 0;
626 : 0 : return 0;
627 : : }
628 : :
629 : 14094482 : const unsigned* vect = instance.vertAdjMap[topo - FIRST_FACE][index];
630 : 14094482 : num_adj_out = vect[0];
631 : 14094482 : return vect + 1;
632 : : }
633 : :
634 : 81692 : const unsigned* TopologyInfo::reverse_vertex_adjacency_offsets( EntityTopology topo, unsigned index,
635 : : unsigned& num_adj_out )
636 : : {
637 : 81692 : const unsigned count = corners( topo );
638 [ + - ][ - + ]: 81692 : if( !count || index >= count )
639 : : {
640 : 0 : num_adj_out = 0;
641 : 0 : return 0;
642 : : }
643 : :
644 : 81692 : const unsigned* vect = instance.revVertAdjIdx[topo - FIRST_FACE][index];
645 : 81692 : num_adj_out = vect[0];
646 : 81692 : return vect + 1;
647 : : }
648 : :
649 : 0 : bool TopologyInfo::compare_sides( const size_t* verts1, EntityTopology type1, unsigned side1, const size_t* verts2,
650 : : EntityTopology type2, unsigned side2, unsigned side_dim, MsqError& err )
651 : : {
652 : : const unsigned *conn1, *conn2;
653 : : unsigned len1, len2;
654 : :
655 [ # # ]: 0 : conn1 = side_vertices( type1, side_dim, side1, len1, err );
656 [ # # ][ # # ]: 0 : MSQ_ERRZERO( err );
[ # # ][ # # ]
[ # # ]
657 [ # # ]: 0 : conn2 = side_vertices( type2, side_dim, side2, len2, err );
658 [ # # ][ # # ]: 0 : MSQ_ERRZERO( err );
[ # # ][ # # ]
[ # # ]
659 : :
660 : : // obviously not the same if different number of vertices
661 : : // (triangular face cannot match quadrilateral face)
662 [ # # ]: 0 : if( len1 != len2 ) return false;
663 : :
664 : : // Find location (i) in vertices of side of second element
665 : : // that matches the first vertex in the side of the first
666 : : // element.
667 : : unsigned i, j;
668 [ # # ]: 0 : for( i = 0; i < len2; ++i )
669 [ # # ]: 0 : if( verts1[conn1[0]] == verts2[conn2[i]] ) break;
670 : : // If not found, then no match
671 [ # # ]: 0 : if( i == len2 ) return false;
672 : :
673 : : // Try comparing side connectivity in forward order
674 [ # # ]: 0 : for( j = 1; j < len1; ++j )
675 [ # # ]: 0 : if( verts1[conn1[j]] != verts2[conn2[( i + j ) % len2]] ) break;
676 : : // If they match, we're done
677 [ # # ]: 0 : if( j == len1 ) return true;
678 : :
679 : : // Try comparing in reverse order
680 [ # # ]: 0 : for( j = 1; j < len1; ++j )
681 [ # # ]: 0 : if( verts1[conn1[j]] != verts2[conn2[( i + len2 - j ) % len2]] ) return false;
682 : : // If here, matched in reverse order
683 : 0 : return true;
684 : : }
685 : :
686 : 0 : unsigned TopologyInfo::find_edge( EntityTopology topo, const unsigned* side_vertices, bool& reversed_out,
687 : : MsqError& err )
688 : : {
689 [ # # ]: 0 : if( dimension( topo ) <= 1 )
690 : : {
691 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "Invalid element dimension" );
692 : 0 : return (unsigned)-1;
693 : : }
694 : :
695 [ # # ]: 0 : for( unsigned i = 0; i < edges( topo ); ++i )
696 : : {
697 : 0 : const unsigned* edge = edge_vertices( topo, i, err );
698 [ # # ][ # # ]: 0 : MSQ_ERRZERO( err );
[ # # ]
699 : :
700 [ # # ][ # # ]: 0 : if( edge[0] == side_vertices[0] && edge[1] == side_vertices[1] )
701 : : {
702 : 0 : reversed_out = false;
703 : 0 : return i;
704 : : }
705 : :
706 [ # # ][ # # ]: 0 : if( edge[0] == side_vertices[1] && edge[1] == side_vertices[0] )
707 : : {
708 : 0 : reversed_out = true;
709 : 0 : return i;
710 : : }
711 : : }
712 : :
713 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "No such edge" );
714 : 0 : return (unsigned)-1;
715 : : }
716 : :
717 : 0 : unsigned TopologyInfo::find_face( EntityTopology topo, const unsigned* side_vertices, unsigned num_vertices,
718 : : bool& reversed_out, MsqError& err )
719 : : {
720 [ # # ]: 0 : if( dimension( topo ) <= 2 )
721 : : {
722 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "Invalid element dimension" );
723 : 0 : return (unsigned)-1;
724 : : }
725 : :
726 [ # # ]: 0 : for( unsigned i = 0; i < faces( topo ); ++i )
727 : : {
728 : : unsigned j, n, offset;
729 [ # # ]: 0 : const unsigned* face = face_vertices( topo, i, n, err );
730 [ # # ][ # # ]: 0 : MSQ_ERRZERO( err );
[ # # ][ # # ]
[ # # ]
731 [ # # ]: 0 : if( n != num_vertices ) continue;
732 : :
733 [ # # ]: 0 : for( offset = 0; offset < num_vertices; ++offset )
734 [ # # ]: 0 : if( face[offset] == side_vertices[0] ) break;
735 [ # # ]: 0 : if( offset == num_vertices ) continue;
736 : :
737 [ # # ]: 0 : for( j = 1; j < num_vertices; ++j )
738 [ # # ]: 0 : if( side_vertices[j] != face[( offset + j ) % num_vertices] ) break;
739 [ # # ]: 0 : if( j == num_vertices )
740 : : {
741 : 0 : reversed_out = false;
742 : 0 : return i;
743 : : }
744 : :
745 [ # # ]: 0 : for( j = 1; j < num_vertices; ++j )
746 [ # # ]: 0 : if( side_vertices[j] != face[( offset + num_vertices - j ) % num_vertices] ) break;
747 [ # # ]: 0 : if( j == num_vertices )
748 : : {
749 : 0 : reversed_out = true;
750 : 0 : return i;
751 : : }
752 : : }
753 : :
754 [ # # ]: 0 : MSQ_SETERR( err )( MsqError::INVALID_ARG, "No such face" );
755 : 0 : return (unsigned)-1;
756 : : }
757 : :
758 : 0 : void TopologyInfo::find_side( EntityTopology topo, const unsigned* side_vertices, unsigned num_vertices,
759 : : unsigned& dimension_out, unsigned& number_out, bool& reversed_out, MsqError& err )
760 : : {
761 [ # # # # ]: 0 : switch( num_vertices )
762 : : {
763 : : case 1:
764 : 0 : dimension_out = 0;
765 : 0 : number_out = *side_vertices;
766 : 0 : reversed_out = false;
767 [ # # ]: 0 : if( *side_vertices >= corners( topo ) ) MSQ_SETERR( err )
768 [ # # ]: 0 : ( MsqError::INVALID_ARG, "Invalid corner number: %u\n", *side_vertices );
769 : 0 : break;
770 : : case 2:
771 : 0 : dimension_out = 1;
772 [ # # ][ # # ]: 0 : number_out = find_edge( topo, side_vertices, reversed_out, err );MSQ_CHKERR( err );
773 : 0 : break;
774 : : case 3:
775 : : case 4:
776 : 0 : dimension_out = 2;
777 [ # # ][ # # ]: 0 : number_out = find_face( topo, side_vertices, num_vertices, reversed_out, err );MSQ_CHKERR( err );
778 : 0 : break;
779 : : default:
780 : : MSQ_SETERR( err )
781 [ # # ]: 0 : ( MsqError::UNSUPPORTED_ELEMENT, "Invalid number of side vertices: %u\n", num_vertices );
782 : 0 : break;
783 : : }
784 : 0 : }
785 : :
786 [ + - ][ + - ]: 128 : } // namespace MBMesquite
|