1 /*
2  * Copyright (c) 2005 Sandia Corporation. Under the terms of Contract
3  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement
4  * retains certain rights in this software.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *
13  *     * Redistributions in binary form must reproduce the above
14  *       copyright notice, this list of conditions and the following
15  *       disclaimer in the documentation and/or other materials provided
16  *       with the distribution.
17  *
18  *     * Neither the name of Sandia Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35 /*****************************************************************************
36 *
37 * exgssn - ex_get_side_set_node_list
38 *
39 * entry conditions -
40 *   input parameters:
41 *       int     exoid                   exodus file id
42 *       int     side_set_id             side set id
43 *
44 * exit conditions -
45 *       int     *side_set_node_cnt_list returned array of number of nodes for
46 *                                       side or face
47 *       int     *side_set_node_list     array of nodes
48 *
49 * revision history -
50 *
51 *
52 *****************************************************************************/
53 
54 #include <ctype.h>
55 #include <string.h>
56 #include <stdlib.h>
57 #include "exodusII.h"
58 #include "exodusII_int.h"
59 /*!
60  * This routine is designed to read the Exodus II V 2.0 side set side
61  * definition  and return a ExodusI style side set node definition.
62  */
63 
ex_get_side_set_node_list(int exoid,int side_set_id,int * side_set_node_cnt_list,int * side_set_node_list)64 int ex_get_side_set_node_list(int exoid,
65                           int side_set_id,
66                           int *side_set_node_cnt_list,
67                           int *side_set_node_list)
68 {
69   size_t m;
70   int i, j;
71   int  num_side_sets, num_elem_blks, num_df, ndim;
72   int tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0;
73   int connect_offset, side_num, node_pos;
74   int *elem_blk_ids = NULL;
75   int *connect = NULL;
76   int *ss_elem_ndx = NULL;
77   int *ss_elem_node_ndx = NULL;
78   int *ss_parm_ndx = NULL;
79   int *side_set_elem_list = NULL;
80   int *side_set_side_list = NULL;
81   int elem_ctr, node_ctr, elem_num_pos;
82   int num_elem_in_blk, num_nodes_per_elem, num_attr;
83   float fdum;
84   char *cdum, elem_type[MAX_STR_LENGTH+1];
85 
86   struct elem_blk_parm  *elem_blk_parms;
87 
88 /* side to node translation tables -
89      These tables are used to look up the side number based on the
90      first and second node in the side/face list. The side node order
91      is found in the original Exodus document, SAND87-2997. The element
92      node order is found in the ExodusII document, SAND92-2137. These
93      tables were generated by following the right-hand rule for determining
94      the outward normal.
95 */
96   /* triangle */
97   static int tri_table[3][3] = {
98   /*   1        2        3                                             side   */
99     {1,2,4}, {2,3,5}, {3,1,6}                                       /* nodes  */
100   };
101 
102   /* triangle 3d */
103   static int tri3_table[5][7] = {
104   /*       1                2                                          side   */
105     {1,2,3,4,5,6,7}, {3,2,1,6,5,4,7},                               /* nodes  */
106   /*       3              4              5                             side   */
107     {1,2,4,0,0,0,0}, {2,3,5,0,0,0,0}, {3,1,6,0,0,0,0}               /* nodes  */
108   };
109 
110   /* quad */
111   static int quad_table[4][3] = {
112   /*   1        2        3        4                                    side   */
113     {1,2,5}, {2,3,6}, {3,4,7}, {4,1,8}                              /* nodes  */
114   };
115 
116   /* shell */
117   static int shell_table[6][8] = {
118   /*        1                  2                                       side   */
119     {1,2,3,4,5,6,7,8}, {1,4,3,2,8,7,6,5} ,                          /* nodes  */
120   /*        3                  4                                       side   */
121     {1,2,5,0,0,0,0,0}, {2,3,6,0,0,0,0,0} ,                          /* nodes  */
122   /*        5                  6                                       side   */
123     {3,4,7,0,0,0,0,0}, {4,1,8,0,0,0,0,0}                            /* nodes  */
124   };
125 
126   /* tetra */
127   static int tetra_table[4][6] = {
128   /*      1              2               3               4            side   */
129     {1,2,4,5,9,8}, {2,3,4,6,10,9}, {1,4,3,8,10,7}, {1,3,2,7,6,5}   /* nodes  */
130   };
131 
132   /* wedge */
133   static int wedge_table[5][8] = {
134   /*        1                     2                     3              side   */
135     {1,2,5,4,7,11,13,10}, {2,3,6,5,8,12,14,11}, {1,4,6,3,10,15,12,9},
136   /*        4                  5                                       side   */
137     {1,3,2,0,9,8,7,0}, {4,5,6,0,13,14,15,0}                         /* nodes  */
138   };
139 
140   /* hex */
141   static int hex_table[6][9] = {
142   /*         1                        2                                side   */
143     {1,2,6,5,9,14,17,13,26}, {2,3,7,6,10,15,18,14,25},              /* nodes  */
144   /*         3                        4                                side   */
145     {3,4,8,7,11,16,19,15,27}, {1,5,8,4,13,20,16,12,24},             /* nodes  */
146   /*         5                        6                                side   */
147     {1,4,3,2,12,11,10,9,22},  {5,6,7,8,17,18,19,20,23}              /* nodes  */
148   };
149 
150   /* pyramid */
151   static int pyramid_table[5][8] = {
152   /*          1                   2                    3              side   */
153     {1,2,5,0,6,11,10,0}, {2,3,5,0,7,12,11,0}, {3,4,5,0,8,13,12,0}, /* nodes  */
154   /*          4                  5                                    side   */
155     {1,5,4,0,10,13,9,0}, {1,4,3,2,9,8,7,6}                         /* nodes  */
156   };
157 
158 
159   char errmsg[MAX_ERR_LENGTH];
160 
161   exerrval = 0; /* clear error code */
162 
163   cdum = 0; /* initialize even though it is not used */
164 
165 /* first check if any side sets are specified */
166 /* inquire how many side sets have been stored */
167 
168   if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1)
169   {
170     sprintf(errmsg,
171            "Error: failed to get number of side sets in file id %d",exoid);
172     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
173     return(EX_FATAL);
174   }
175 
176   if (num_side_sets == 0)
177   {
178     sprintf(errmsg,
179            "Warning: no side sets defined in file id %d",exoid);
180     ex_err("ex_get_side_set_node_list",errmsg,EX_WARN);
181     return(EX_WARN);
182   }
183 
184 /* Lookup index of side set id in VAR_SS_IDS array */
185 
186   ex_id_lkup(exoid,EX_SIDE_SET,side_set_id);
187   if (exerrval != 0)
188   {
189      if (exerrval == EX_NULLENTITY)
190      {
191        sprintf(errmsg,
192               "Warning: side set %d is NULL in file id %d",
193                side_set_id,exoid);
194        ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
195        return (EX_WARN);
196      }
197      else
198      {
199 
200      sprintf(errmsg,
201      "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d",
202              side_set_id,exoid);
203      ex_err("ex_get_side_set_node_list",errmsg,exerrval);
204      return (EX_FATAL);
205      }
206   }
207 
208   if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1)
209   {
210     sprintf(errmsg,
211            "Error: failed to get number of element blocks in file id %d",exoid);
212     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
213     return(EX_FATAL);
214   }
215 
216   if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1)
217   {
218     sprintf(errmsg,
219            "Error: failed to get total number of elements in file id %d",exoid);
220     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
221     return(EX_FATAL);
222   }
223 
224 /* get the dimensionality of the coordinates;  this is necessary to
225    distinguish between 2d TRIs and 3d TRIs */
226 
227   if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1)
228   {
229     sprintf(errmsg,
230            "Error: failed to get dimensionality in file id %d",exoid);
231     ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
232     return(EX_FATAL);
233   }
234 
235   /* First determine the  # of elements in the side set*/
236   if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1)
237   {
238     sprintf(errmsg,
239          "Error: failed to get number of elements in side set %d in file id %d",
240             side_set_id, exoid);
241     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
242     return(EX_FATAL);
243   }
244 
245   /* Allocate space for the side set element list */
246   if (!(side_set_elem_list=malloc(tot_num_ss_elem*sizeof(int))))
247   {
248     exerrval = EX_MEMFAIL;
249     sprintf(errmsg,
250     "Error: failed to allocate space for side set element list for file id %d",
251             exoid);
252     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
253     return (EX_FATAL);
254   }
255 
256   /* Allocate space for the side set side list */
257   if (!(side_set_side_list=malloc(tot_num_ss_elem*sizeof(int))))
258   {
259     free(side_set_elem_list);
260     exerrval = EX_MEMFAIL;
261     sprintf(errmsg,
262     "Error: failed to allocate space for side set side list for file id %d",
263             exoid);
264     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
265     return (EX_FATAL);
266   }
267 
268   if (ex_get_side_set(exoid, side_set_id,
269                       side_set_elem_list, side_set_side_list) == -1)
270   {
271     free(side_set_elem_list);
272     free(side_set_side_list);
273     sprintf(errmsg,
274     "Error: failed to get side set %d in file id %d",
275             side_set_id, exoid);
276     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
277     return (EX_FATAL);
278   }
279 
280   /* Allocate space for the ss element index array */
281   if (!(ss_elem_ndx= malloc(tot_num_ss_elem*sizeof(int))))
282   {
283     free(side_set_elem_list);
284     free(side_set_side_list);
285     exerrval = EX_MEMFAIL;
286     sprintf(errmsg,
287  "Error: failed to allocate space for side set elem sort array for file id %d",
288             exoid);
289     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
290     return (EX_FATAL);
291   }
292 
293   /* Sort side set element list into index array  - non-destructive */
294   for (i=0;i<tot_num_ss_elem;i++)
295     ss_elem_ndx[i] = i; /* init index array to current position */
296 
297   ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
298 
299 
300   /* Allocate space for the element block ids */
301   if (!(elem_blk_ids= malloc(num_elem_blks*sizeof(int))))
302   {
303     exerrval = EX_MEMFAIL;
304     free(ss_elem_ndx);
305     free(side_set_side_list);
306     free(side_set_elem_list);
307     sprintf(errmsg,
308         "Error: failed to allocate space for element block ids for file id %d",
309             exoid);
310     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
311     return (EX_FATAL);
312   }
313 
314   if (ex_get_elem_blk_ids(exoid, elem_blk_ids) == -1)
315   {
316     free(elem_blk_ids);
317     free(ss_elem_ndx);
318     free(side_set_side_list);
319     free(side_set_elem_list);
320     sprintf(errmsg,
321            "Error: failed to get element block ids in file id %d",
322             exoid);
323     ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
324     return(EX_FATAL);
325   }
326 
327   /* Allocate space for the element block params */
328   if (!(elem_blk_parms= malloc(num_elem_blks*sizeof(struct elem_blk_parm))))
329   {
330     free(elem_blk_ids);
331     free(ss_elem_ndx);
332     free(side_set_side_list);
333     free(side_set_elem_list);
334     exerrval = EX_MEMFAIL;
335     sprintf(errmsg,
336       "Error: failed to allocate space for element block params for file id %d",
337             exoid);
338     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
339     return (EX_FATAL);
340   }
341 
342   elem_ctr = 0;
343   for (i=0; i<num_elem_blks; i++)
344   {
345     /* read in an element block parameter */
346     if ((ex_get_elem_block (exoid,
347                             elem_blk_ids[i],
348                             elem_type,
349                             &num_elem_in_blk,
350                             &num_nodes_per_elem,
351                             &num_attr)) == -1)
352     {
353       free(elem_blk_parms);
354       free(elem_blk_ids);
355       free(ss_elem_ndx);
356       free(side_set_side_list);
357       free(side_set_elem_list);
358       sprintf(errmsg,
359              "Error: failed to get element block %d parameters in file id %d",
360               elem_blk_ids[i], exoid);
361       ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
362       return(EX_FATAL);
363     }
364 
365     elem_blk_parms[i].num_elem_in_blk = num_elem_in_blk;
366     elem_blk_parms[i].num_nodes_per_elem = num_nodes_per_elem;
367     elem_blk_parms[i].num_attr = num_attr;
368 
369     for (m=0; m < strlen(elem_type); m++)
370       elem_blk_parms[i].elem_type[m] = toupper(elem_type[m]);
371     elem_blk_parms[i].elem_type[m] = EX_EL_NULL_ELEMENT;
372 
373     if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
374     {
375       elem_blk_parms[i].elem_type_val = EX_EL_CIRCLE;
376       /* set side set node stride */
377         elem_blk_parms[i].num_nodes_per_side[0] = 1;
378     }
379     else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
380     {
381       elem_blk_parms[i].elem_type_val = EX_EL_SPHERE;
382       /* set side set node stride */
383         elem_blk_parms[i].num_nodes_per_side[0] = 1;
384     }
385     else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
386     {
387       elem_blk_parms[i].elem_type_val = EX_EL_QUAD;
388       /* determine side set node stride */
389       if (elem_blk_parms[i].num_nodes_per_elem == 4)
390         elem_blk_parms[i].num_nodes_per_side[0] = 2;
391       else if (elem_blk_parms[i].num_nodes_per_elem == 5)
392         elem_blk_parms[i].num_nodes_per_side[0] = 2;
393       else
394         elem_blk_parms[i].num_nodes_per_side[0] = 3;
395     }
396     else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
397     {
398       elem_blk_parms[i].elem_type_val = EX_EL_TRIANGLE;
399       /* set default side set node stride */
400       if (ndim == 2)  /* 2d TRIs */
401       {
402         if (elem_blk_parms[i].num_nodes_per_elem == 3)
403           elem_blk_parms[i].num_nodes_per_side[0] = 2;
404         else
405           elem_blk_parms[i].num_nodes_per_side[0] = 3;
406       }
407       else if (ndim == 3)  /* 3d TRIs */
408       {
409         if (elem_blk_parms[i].num_nodes_per_elem == 3)
410           elem_blk_parms[i].num_nodes_per_side[0] = 3;
411         else
412           elem_blk_parms[i].num_nodes_per_side[0] = 6;
413       }
414     }
415     else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
416     {
417       elem_blk_parms[i].elem_type_val = EX_EL_SHELL;
418       /* determine side set node stride */
419       if (elem_blk_parms[i].num_nodes_per_elem == 2) /* KLUDGE for 2D Shells*/
420         elem_blk_parms[i].num_nodes_per_side[0] = 2;
421       else if (elem_blk_parms[i].num_nodes_per_elem == 4)
422         elem_blk_parms[i].num_nodes_per_side[0] = 4;
423       else
424         elem_blk_parms[i].num_nodes_per_side[0] = 8;
425     }
426     else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
427     {
428       elem_blk_parms[i].elem_type_val = EX_EL_HEX;
429       /* determine side set node stride */
430       if (elem_blk_parms[i].num_nodes_per_elem == 8)  /* 8-node bricks */
431         elem_blk_parms[i].num_nodes_per_side[0] = 4;
432       else if (elem_blk_parms[i].num_nodes_per_elem == 9)  /* 9-node bricks */
433         elem_blk_parms[i].num_nodes_per_side[0] = 4;
434       else if (elem_blk_parms[i].num_nodes_per_elem == 12)  /* HEXSHELLS */
435         elem_blk_parms[i].num_nodes_per_side[0] = 4;
436       else if (elem_blk_parms[i].num_nodes_per_elem == 27)  /* 27-node bricks */
437         elem_blk_parms[i].num_nodes_per_side[0] = 9;
438       else
439         elem_blk_parms[i].num_nodes_per_side[0] = 8;
440     }
441     else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
442     {
443       elem_blk_parms[i].elem_type_val = EX_EL_TETRA;
444       /* determine side set node stride */
445       if (elem_blk_parms[i].num_nodes_per_elem == 4)
446         elem_blk_parms[i].num_nodes_per_side[0] = 3;
447       else if (elem_blk_parms[i].num_nodes_per_elem == 8)
448         elem_blk_parms[i].num_nodes_per_side[0] = 4;
449       else
450         elem_blk_parms[i].num_nodes_per_side[0] = 6;
451     }
452     else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
453     {
454       elem_blk_parms[i].elem_type_val = EX_EL_WEDGE;
455       /* determine side set node stride */
456       if (elem_blk_parms[i].num_nodes_per_elem == 6)
457         elem_blk_parms[i].num_nodes_per_side[0] = 4;
458       else
459         elem_blk_parms[i].num_nodes_per_side[0] = 8;
460     }
461     else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
462     {
463       elem_blk_parms[i].elem_type_val = EX_EL_PYRAMID;
464       /* determine side set node stride */
465       if (elem_blk_parms[i].num_nodes_per_elem == 5)
466         elem_blk_parms[i].num_nodes_per_side[0] = 4;
467       else
468         elem_blk_parms[i].num_nodes_per_side[0] = 8;
469     }
470     else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
471     {
472       elem_blk_parms[i].elem_type_val = EX_EL_BEAM;
473       /* determine side set node stride */
474       if (elem_blk_parms[i].num_nodes_per_elem == 2)
475         elem_blk_parms[i].num_nodes_per_side[0] = 2;
476       else
477         elem_blk_parms[i].num_nodes_per_side[0] = 3;
478     }
479     else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
480               (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0) ||
481               (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
482     {
483       elem_blk_parms[i].elem_type_val = EX_EL_TRUSS;
484       /* determine side set node stride */
485       if (elem_blk_parms[i].num_nodes_per_elem == 2)
486         elem_blk_parms[i].num_nodes_per_side[0] = 2;
487       else
488         elem_blk_parms[i].num_nodes_per_side[0] = 3;
489     }
490     else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
491     {
492       elem_blk_parms[i].elem_type_val = EX_EL_NULL_ELEMENT;
493       elem_blk_parms[i].num_nodes_per_side[0] = 0;
494       elem_blk_parms[i].num_elem_in_blk = 0;
495     }
496     else
497     { /* unsupported element type; no problem if no sides specified for
498          this element block */
499       elem_blk_parms[i].elem_type_val = EX_EL_UNK;
500       elem_blk_parms[i].num_nodes_per_side[0] = 0;
501     }
502     elem_blk_parms[i].elem_blk_id = elem_blk_ids[i];    /* save id */
503     elem_ctr += elem_blk_parms[i].num_elem_in_blk;
504     elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
505   }
506 
507 
508   /* Allocate space for the ss element to element block parameter index array */
509   if (!(ss_parm_ndx=malloc(tot_num_ss_elem*sizeof(int))))
510   {
511     free(elem_blk_parms);
512     free(elem_blk_ids);
513     free(ss_elem_ndx);
514     free(side_set_side_list);
515     free(side_set_elem_list);
516     exerrval = EX_MEMFAIL;
517     sprintf(errmsg,
518 	    "Error: failed to allocate space for side set elem parms index for file id %d",
519             exoid);
520     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
521     return (EX_FATAL);
522   }
523 
524 
525   /* Allocate space for the ss element to node list index array */
526   if (!(ss_elem_node_ndx=malloc(tot_num_ss_elem*sizeof(int))))
527   {
528     free(ss_parm_ndx);
529     free(elem_blk_parms);
530     free(elem_blk_ids);
531     free(ss_elem_ndx);
532     free(side_set_side_list);
533     free(side_set_elem_list);
534     exerrval = EX_MEMFAIL;
535     sprintf(errmsg,
536 	    "Error: failed to allocate space for side set elem to node index for file id %d",
537             exoid);
538     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
539 
540     return (EX_FATAL);
541   }
542 
543 /* Build side set element to node list index and side set element
544    parameter index.
545 */
546   node_ctr = 0;
547   for (i=0;i<tot_num_ss_elem;i++) {
548     for (j=0; j<num_elem_blks; j++) {
549       if (elem_blk_parms[j].elem_type_val != EX_EL_NULL_ELEMENT)
550 	if (side_set_elem_list[i] <= elem_blk_parms[j].elem_ctr)
551 	  break;
552     }
553 
554     if (j >= num_elem_blks) {
555       exerrval = EX_BADPARAM;
556       sprintf(errmsg,
557              "Error: Invalid element number %d found in side set %d in file %d",
558               side_set_elem_list[i], side_set_id, exoid);
559       free(ss_parm_ndx);
560       free(ss_elem_node_ndx);
561       free(elem_blk_parms);
562       free(elem_blk_ids);
563       free(ss_elem_ndx);
564       free(side_set_side_list);
565       free(side_set_elem_list);
566       ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
567       return (EX_FATAL);
568     }
569 
570     ss_parm_ndx[i] = j; /* assign parameter block index */
571     ss_elem_node_ndx[i] = node_ctr;     /* assign node list index */
572 
573     /* Update node_ctr (which points to next node in chain */
574 
575     /* WEDGEs with 3 node sides (side 4 or 5) are special cases */
576     if (elem_blk_parms[j].elem_type_val == EX_EL_WEDGE &&
577         (side_set_side_list[i] == 4 || side_set_side_list[i] == 5))
578     {
579       if (elem_blk_parms[j].num_nodes_per_elem == 6)
580         node_ctr += 3;  /* 3 node side */
581       else
582         node_ctr += 6;  /* 6 node side */
583     }
584     /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */
585     else if (elem_blk_parms[j].elem_type_val == EX_EL_PYRAMID &&
586              (side_set_side_list[i] < 5))
587     {
588       if (elem_blk_parms[j].num_nodes_per_elem == 5)
589         node_ctr += 3;  /* 3 node side */
590       else
591         node_ctr += 6;  /* 6 node side */
592     }
593     /* side numbers 3,4,5,6 for SHELLs are also special */
594     else if (elem_blk_parms[j].elem_type_val == EX_EL_SHELL &&
595         (side_set_side_list[i] > 2 ))
596     {
597       if (elem_blk_parms[j].num_nodes_per_elem == 4)
598         node_ctr += 2;  /* 2 node side */
599       else
600         node_ctr += 3;  /* 3 node side */
601     }
602     /* side numbers 3,4,5 for 3d TRIs are also special */
603     else if (elem_blk_parms[j].elem_type_val == EX_EL_TRIANGLE &&
604              ndim == 3 &&
605              side_set_side_list[i] > 2 )
606     {
607       if (elem_blk_parms[j].num_nodes_per_elem == 3)  /* 3-node TRI */
608         node_ctr += 2;  /* 2 node side */
609       else   /* 6-node TRI */
610         node_ctr += 3;  /* 3 node side */
611     }
612     else /* all other element types */
613       node_ctr += elem_blk_parms[j].num_nodes_per_side[0];
614   }
615 
616   /* All setup, ready to go ... */
617 
618   elem_ctr=0;
619 
620   for (j=0; j < tot_num_ss_elem; j++) {
621 
622     if (side_set_elem_list[ss_elem_ndx[j]] > elem_ctr) {
623       /* release connectivity array space and get next one */
624       if (elem_ctr > 0) {
625         free(connect);
626       }
627 
628       /* Allocate space for the connectivity array for new element block */
629       if (!(connect=malloc(elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk*
630                            elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem*
631                            (int)sizeof(int))))
632       {
633         free(elem_blk_parms);
634         free(elem_blk_ids);
635         free(ss_elem_ndx);
636         free(ss_elem_node_ndx);
637         free(ss_parm_ndx);
638         free(side_set_side_list);
639         free(side_set_elem_list);
640         exerrval = EX_MEMFAIL;
641         sprintf(errmsg,
642         "Error: failed to allocate space for connectivity array for file id %d",
643                 exoid);
644         ex_err("ex_get_side_set_node_list",errmsg,exerrval);
645         return (EX_FATAL);
646       }
647 
648       /* get connectivity array */
649       if (ex_get_elem_conn(exoid,
650 			   elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
651 			   connect) == -1)
652       {
653         free(connect);
654         free(elem_blk_parms);
655         free(elem_blk_ids);
656         free(ss_elem_ndx);
657         free(ss_elem_node_ndx);
658         free(ss_parm_ndx);
659         free(side_set_side_list);
660         free(side_set_elem_list);
661         sprintf(errmsg,
662         "Error: failed to allocate space for connectivity array for file id %d",
663                 exoid);
664         ex_err("ex_get_side_set_node_list",errmsg,exerrval);
665         return (EX_FATAL);
666       }
667       elem_ctr = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr;
668     }
669     /*  For each side in side set, use the appropriate lookup table to
670 	determine the nodes from the connect array. */
671 
672     elem_num = side_set_elem_list[ss_elem_ndx[j]]-1;/* element number 0-based*/
673     /* calculate the relative element number position in it's block*/
674 
675     elem_num_pos = elem_num -
676                   (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr -
677                    elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk);
678 
679     /* calculate the beginning of the node list for this element by
680          using the ss_elem_node_ndx index into the side_sets_node_index
681          and adding the element number position * number of nodes per elem */
682 
683     num_nodes_per_elem = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem;
684     node_pos = ss_elem_node_ndx[ss_elem_ndx[j]];
685     connect_offset = num_nodes_per_elem*elem_num_pos;
686     side_num = side_set_side_list[ss_elem_ndx[j]]-1;
687 
688     switch (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type_val)
689     {
690       case EX_EL_CIRCLE:
691       case EX_EL_SPHERE:
692       { /* Note: no side-node lookup table is used for this simple case */
693         side_set_node_list[node_pos] = connect[connect_offset];
694         side_set_node_cnt_list[ss_elem_ndx[j]] = 1;   /* 1 node object */
695         break;
696       }
697       case EX_EL_TRUSS:
698       case EX_EL_BEAM:
699       { /* Note: no side-node lookup table is used for this simple case */
700         side_set_node_list[node_pos] = connect[connect_offset];
701         side_set_node_list[node_pos+1] = connect[connect_offset+1];
702         side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
703         if (num_nodes_per_elem > 2)
704         {
705           side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
706           side_set_node_list[node_pos+2] = connect[connect_offset+2];
707         }
708         break;
709       }
710       case EX_EL_TRIANGLE:
711       {
712         if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
713         {
714           exerrval = EX_BADPARAM;
715           sprintf(errmsg,
716                  "Error: Invalid triangle edge number %d in file id %d",
717                   side_num+1, exoid);
718           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
719           free(connect);
720           free(elem_blk_parms);
721           free(elem_blk_ids);
722           free(ss_elem_ndx);
723           free(ss_elem_node_ndx);
724           free(ss_parm_ndx);
725           free(side_set_side_list);
726           free(side_set_elem_list);
727           return(EX_FATAL);
728         }
729 
730         if (ndim == 2)   /* 2d TRIs */
731         {
732           side_set_node_list[node_pos] =
733             connect[connect_offset+tri_table[side_num][0]-1];
734           side_set_node_list[node_pos+1] =
735             connect[connect_offset+tri_table[side_num][1]-1];
736           side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
737           if (num_nodes_per_elem > 3)   /* 6-node TRI  */
738           {
739             side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
740             side_set_node_list[node_pos+2] =
741               connect[connect_offset+tri_table[side_num][2]-1];
742           }
743         }
744         else if (ndim == 3)  /* 3d TRIs */
745         {
746           side_set_node_list[node_pos] =
747             connect[connect_offset+tri3_table[side_num][0]-1];
748           side_set_node_list[node_pos+1] =
749             connect[connect_offset+tri3_table[side_num][1]-1];
750           side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
751           if (side_num+1 <= 2)  /* 3- or 6-node face */
752           {
753             if (num_nodes_per_elem == 3)  /* 3-node face */
754             {
755               side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
756               side_set_node_list[node_pos+2] =
757                 connect[connect_offset+tri3_table[side_num][2]-1];
758             }
759             else   /* 6-node face */
760             {
761               side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */
762               side_set_node_list[node_pos+2] =
763                 connect[connect_offset+tri3_table[side_num][2]-1];
764               side_set_node_list[node_pos+3] =
765                 connect[connect_offset+tri3_table[side_num][3]-1];
766               side_set_node_list[node_pos+4] =
767                 connect[connect_offset+tri3_table[side_num][4]-1];
768               side_set_node_list[node_pos+5] =
769                 connect[connect_offset+tri3_table[side_num][5]-1];
770             }
771           }
772           else /* 2- or 3-node edge */
773           {
774             if (num_nodes_per_elem > 3)  /* 3-node edge */
775             {
776               side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
777               side_set_node_list[node_pos+2] =
778                 connect[connect_offset+tri3_table[side_num][2]-1];
779             }
780           }
781         }
782         break;
783       }
784       case EX_EL_QUAD:
785       {
786         if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
787         {
788           exerrval = EX_BADPARAM;
789           sprintf(errmsg,
790                  "Error: Invalid quad edge number %d in file id %d",
791                   side_num+1, exoid);
792           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
793           free(connect);
794           free(elem_blk_parms);
795           free(elem_blk_ids);
796           free(ss_elem_ndx);
797           free(ss_elem_node_ndx);
798           free(ss_parm_ndx);
799           free(side_set_side_list);
800           free(side_set_elem_list);
801           return(EX_FATAL);
802         }
803 
804         side_set_node_list[node_pos] =
805           connect[connect_offset+quad_table[side_num][0]-1];
806         side_set_node_list[node_pos+1] =
807           connect[connect_offset+quad_table[side_num][1]-1];
808         side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
809         if (num_nodes_per_elem > 5)
810         {
811           side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
812           side_set_node_list[node_pos+2] =
813             connect[connect_offset+quad_table[side_num][2]-1];
814         }
815         break;
816       }
817       case EX_EL_SHELL:
818       {
819         if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
820         {
821           exerrval = EX_BADPARAM;
822           sprintf(errmsg,
823                  "Error: Invalid shell face number %d in file id %d",
824                   side_num+1, exoid);
825           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
826           free(connect);
827           free(elem_blk_parms);
828           free(elem_blk_ids);
829           free(ss_elem_ndx);
830           free(ss_elem_node_ndx);
831           free(ss_parm_ndx);
832           free(side_set_side_list);
833           free(side_set_elem_list);
834           return(EX_FATAL);
835         }
836 
837         side_set_node_list[node_pos] =
838           connect[connect_offset+shell_table[side_num][0]-1];
839         side_set_node_list[node_pos+1] =
840           connect[connect_offset+shell_table[side_num][1]-1];
841         side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
842         if (num_nodes_per_elem > 2) /*** KLUDGE for 2D shells ***/
843         {
844           if (side_num+1 <= 2)  /* 4-node face */
845           {
846             side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node object */
847             side_set_node_list[node_pos+2] =
848               connect[connect_offset+shell_table[side_num][2]-1];
849             side_set_node_list[node_pos+3] =
850               connect[connect_offset+shell_table[side_num][3]-1];
851           }
852         }
853         if (num_nodes_per_elem == 8)
854         {
855           if (side_num+1 <= 2)  /* 8-node face */
856           {
857             side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
858             side_set_node_list[node_pos+4] =
859               connect[connect_offset+shell_table[side_num][4]-1];
860             side_set_node_list[node_pos+5] =
861               connect[connect_offset+shell_table[side_num][5]-1];
862             side_set_node_list[node_pos+6] =
863               connect[connect_offset+shell_table[side_num][6]-1];
864             side_set_node_list[node_pos+7] =
865               connect[connect_offset+shell_table[side_num][7]-1];
866           }
867           else
868           {
869             side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node edge */
870             side_set_node_list[node_pos+2] =
871               connect[connect_offset+shell_table[side_num][2]-1];
872           }
873         }
874         break;
875       }
876       case EX_EL_TETRA:
877       {
878         if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
879         {
880           exerrval = EX_BADPARAM;
881           sprintf(errmsg,
882                  "Error: Invalid tetra face number %d in file id %d",
883                   side_num+1, exoid);
884           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
885           free(connect);
886           free(elem_blk_parms);
887           free(elem_blk_ids);
888           free(ss_elem_ndx);
889           free(ss_elem_node_ndx);
890           free(ss_parm_ndx);
891           free(side_set_side_list);
892           free(side_set_elem_list);
893           return(EX_FATAL);
894         }
895 
896         side_set_node_list[node_pos] =
897           connect[connect_offset+tetra_table[side_num][0]-1];
898         side_set_node_list[node_pos+1] =
899           connect[connect_offset+tetra_table[side_num][1]-1];
900         side_set_node_list[node_pos+2] =
901           connect[connect_offset+tetra_table[side_num][2]-1];
902         side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node object */
903         if (num_nodes_per_elem == 8)
904         {
905           side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node object */
906           side_set_node_list[node_pos+3] =
907             connect[connect_offset+tetra_table[side_num][3]-1];
908         }
909         else if (num_nodes_per_elem > 8)
910         {
911           side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */
912           side_set_node_list[node_pos+3] =
913             connect[connect_offset+tetra_table[side_num][3]-1];
914           side_set_node_list[node_pos+4] =
915             connect[connect_offset+tetra_table[side_num][4]-1];
916           side_set_node_list[node_pos+5] =
917             connect[connect_offset+tetra_table[side_num][5]-1];
918         }
919         break;
920       }
921       case EX_EL_WEDGE:
922       {
923         if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
924         {
925           exerrval = EX_BADPARAM;
926           sprintf(errmsg,
927                  "Error: Invalid wedge face number %d in file id %d",
928                   side_num+1, exoid);
929           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
930           free(connect);
931           free(elem_blk_parms);
932           free(elem_blk_ids);
933           free(ss_elem_ndx);
934           free(ss_elem_node_ndx);
935           free(ss_parm_ndx);
936           free(side_set_side_list);
937           free(side_set_elem_list);
938           return(EX_FATAL);
939         }
940 
941         side_set_node_list[node_pos++] =
942           connect[connect_offset+wedge_table[side_num][0]-1];
943         side_set_node_list[node_pos++] =
944           connect[connect_offset+wedge_table[side_num][1]-1];
945         side_set_node_list[node_pos++] =
946           connect[connect_offset+wedge_table[side_num][2]-1];
947 
948         if (wedge_table[side_num][3] == 0) { /* degenerate side? */
949           side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node side */
950         }
951         else
952         {
953           side_set_node_list[node_pos++] =
954             connect[connect_offset+wedge_table[side_num][3]-1];
955           side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node side */
956         }
957 
958 
959         if (num_nodes_per_elem > 6)
960         {
961           side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
962           side_set_node_list[node_pos++] =
963             connect[connect_offset+wedge_table[side_num][4]-1];
964           side_set_node_list[node_pos++] =
965             connect[connect_offset+wedge_table[side_num][5]-1];
966           side_set_node_list[node_pos++] =
967             connect[connect_offset+wedge_table[side_num][6]-1];
968 
969           if (wedge_table[side_num][7] == 0) /* degenerate side? */
970             side_set_node_cnt_list[ss_elem_ndx[j]] = 6;   /* 6 node side */
971           else
972           {
973             side_set_node_list[node_pos++] =
974               connect[connect_offset+wedge_table[side_num][7]-1];
975             side_set_node_cnt_list[ss_elem_ndx[j]] = 8;   /* 8 node side */
976           }
977         }
978         break;
979       }
980       case EX_EL_PYRAMID:
981       {
982         if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
983         {
984           exerrval = EX_BADPARAM;
985           sprintf(errmsg,
986                  "Error: Invalid pyramid face number %d in file id %d",
987                   side_num+1, exoid);
988           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
989           free(connect);
990           free(elem_blk_parms);
991           free(elem_blk_ids);
992           free(ss_elem_ndx);
993           free(ss_elem_node_ndx);
994           free(ss_parm_ndx);
995           free(side_set_side_list);
996           free(side_set_elem_list);
997           return(EX_FATAL);
998         }
999 
1000         side_set_node_list[node_pos++] =
1001           connect[connect_offset+pyramid_table[side_num][0]-1];
1002         side_set_node_list[node_pos++] =
1003           connect[connect_offset+pyramid_table[side_num][1]-1];
1004         side_set_node_list[node_pos++] =
1005           connect[connect_offset+pyramid_table[side_num][2]-1];
1006 
1007         if (pyramid_table[side_num][3] == 0) { /* degenerate side? */
1008           side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node side */
1009         }
1010         else
1011         {
1012           side_set_node_list[node_pos++] =
1013             connect[connect_offset+pyramid_table[side_num][3]-1];
1014           side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node side */
1015         }
1016 
1017 
1018         if (num_nodes_per_elem > 5)
1019         {
1020           side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
1021           side_set_node_list[node_pos++] =
1022             connect[connect_offset+pyramid_table[side_num][4]-1];
1023           side_set_node_list[node_pos++] =
1024             connect[connect_offset+pyramid_table[side_num][5]-1];
1025           side_set_node_list[node_pos++] =
1026             connect[connect_offset+pyramid_table[side_num][6]-1];
1027 
1028           if (pyramid_table[side_num][7] == 0) /* degenerate side? */
1029             side_set_node_cnt_list[ss_elem_ndx[j]] = 6;   /* 6 node side */
1030           else
1031           {
1032             side_set_node_list[node_pos++] =
1033               connect[connect_offset+pyramid_table[side_num][7]-1];
1034             side_set_node_cnt_list[ss_elem_ndx[j]] = 8;   /* 8 node side */
1035           }
1036         }
1037         break;
1038       }
1039       case EX_EL_HEX:
1040       {
1041         if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
1042         {
1043           exerrval = EX_BADPARAM;
1044           sprintf(errmsg,
1045                  "Error: Invalid hex face number %d in file id %d",
1046                   side_num+1, exoid);
1047           ex_err("ex_get_side_set_node_list",errmsg,exerrval);
1048           free(connect);
1049           free(elem_blk_parms);
1050           free(elem_blk_ids);
1051           free(ss_elem_ndx);
1052           free(ss_elem_node_ndx);
1053           free(ss_parm_ndx);
1054           free(side_set_side_list);
1055           free(side_set_elem_list);
1056           return(EX_FATAL);
1057         }
1058 
1059         side_set_node_list[node_pos] =
1060           connect[connect_offset+hex_table[side_num][0]-1];
1061         side_set_node_list[node_pos+1] =
1062           connect[connect_offset+hex_table[side_num][1]-1];
1063         side_set_node_list[node_pos+2] =
1064           connect[connect_offset+hex_table[side_num][2]-1];
1065         side_set_node_list[node_pos+3] =
1066           connect[connect_offset+hex_table[side_num][3]-1];
1067         side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node object */
1068         if (num_nodes_per_elem > 12)   /* more nodes than HEXSHELL */
1069         {
1070           side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
1071           side_set_node_list[node_pos+4] =
1072             connect[connect_offset+hex_table[side_num][4]-1];
1073           side_set_node_list[node_pos+5] =
1074             connect[connect_offset+hex_table[side_num][5]-1];
1075           side_set_node_list[node_pos+6] =
1076             connect[connect_offset+hex_table[side_num][6]-1];
1077           side_set_node_list[node_pos+7] =
1078             connect[connect_offset+hex_table[side_num][7]-1];
1079         }
1080         if (num_nodes_per_elem == 27)                 /* 27-node brick */
1081         {
1082           side_set_node_cnt_list[ss_elem_ndx[j]] = 9; /* 9 node object */
1083           side_set_node_list[node_pos+8] =
1084             connect[connect_offset+hex_table[side_num][8]-1];
1085         }
1086         break;
1087       }
1088       default:
1089       {
1090         exerrval = EX_BADPARAM;
1091         sprintf(errmsg,
1092                "Error: %s is an unsupported element type",
1093                 elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type);
1094         ex_err("ex_get_side_set_node_list",errmsg,exerrval);
1095         return(EX_FATAL);
1096       }
1097     }
1098   }
1099 
1100 
1101   /* All done: release connectivity array space, element block ids array,
1102      element block parameters array, and side set element index array */
1103   free(connect);
1104   free(ss_parm_ndx);
1105   free(elem_blk_ids);
1106   free(elem_blk_parms);
1107   free(ss_elem_ndx);
1108   free(ss_elem_node_ndx);
1109   free(side_set_side_list);
1110   free(side_set_elem_list);
1111 
1112   return(EX_NOERR);
1113 }
1114