Beispiel #1
0
int ex_cvt_nodes_to_sides(int exoid,
                          int *num_elem_per_set,
                          int *num_nodes_per_set,
                          int *side_sets_elem_index,
                          int *side_sets_node_index,
                          int *side_sets_elem_list,
                          int *side_sets_node_list,
                          int *side_sets_side_list)
{
  int i, j, k, m, n;
  int  num_side_sets, num_elem_blks;
  int tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0, ndim;
  int *elem_blk_ids, *connect = 0;
  int *ss_elem_ndx, *ss_elem_node_ndx, *ss_parm_ndx;
  int elem_ctr, node_ctr, elem_num_pos;
  int num_elem_in_blk, num_nodes_per_elem, num_node_per_side, num_attr;
  int *same_elem_type, el_type = -1;
  float fdum;
  char *cdum, elem_type[MAX_STR_LENGTH+1];

  struct elem_blk_parm  *elem_blk_parms;

/* node to side translation tables - 
     These tables are used to look up the side number based on the
     first and second node in the side/face list. The side node order
     is found in the original Exodus document, SAND87-2997. The element
     node order is found in the ExodusII document, SAND92-2137. These
     tables were generated by following the right-hand rule for determining
     the outward normal. Note: Only the more complex 3-D shapes require
     these tables, the simple shapes are trivial - the first node found
     is also the side number.
*/

  /*    1     2   3    4                                          node 1 */
  static int shell_table[2][8]  = {
      {2,4, 3,1, 4,2, 1,3},                                    /* node 2 */
      {1,2, 1,2, 1,2, 1,2}                                     /* side # */
  };

  /*    1     2   3    4                                          node 1 */
  static int shell_edge_table[2][8]  = {
      {2,4, 3,1, 4,2, 1,3},                                    /* node 2 */
      {3,6, 4,3, 5,4, 6,5}                                     /* side # */
  };

  /*    1     2   3                                               node 1 */
  static int trishell_table[2][6]  = {
      {2,3, 3,1, 1,2},                                         /* node 2 */
      {1,2, 1,2, 1,2}                                          /* side # */
  };

  /*     1      2      3      4                                   node 1 */
  static int tetra_table[2][12]  = {
      {2,3,4, 1,3,4, 4,1,2, 1,2,3},                            /* node 2 */
      {1,4,3, 4,2,1, 2,3,4, 1,2,3}                             /* side # */
  };

#if 0
  static int wedge_table[2][18]  = {
  /*     1      2      3      4      5      6                     node 1 */
      {2,4,3, 5,1,3, 6,1,2, 1,6,5, 6,2,4, 4,3,5},              /* node 2 */
      {1,3,4, 1,4,2, 2,3,4, 1,3,5, 5,2,1, 5,3,2}               /* side # */
  };
#endif
  
  static int hex_table[2][24]  = {
  /*     1      2      3      4      5      6      7      8       node 1 */
      {4,2,5, 1,3,6, 7,4,2, 3,1,8, 6,8,1, 5,2,7, 8,6,3, 7,5,4},/* node 2 */
      {5,1,4, 5,2,1, 2,3,5, 5,4,3, 6,4,1, 1,2,6, 6,2,3, 3,6,4} /* side # */
  };

  char errmsg[MAX_ERR_LENGTH];

  (void)side_sets_elem_index;
  (void)side_sets_node_index;

  exerrval = 0; /* clear error code */

  cdum = 0; /* initialize even though it is not used */

/* first check if any side sets are specified */
/* inquire how many side sets have been stored */

  if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0)
  {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,EX_WARN);
    return(EX_WARN);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

/* get the dimensionality of the coordinates;  this is necessary to
   distinguish between 2d TRIs and 3d TRIs */

  if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* First count up # of elements in the side sets*/
  for (i=0;i<num_side_sets;i++)
    tot_num_ss_elem += num_elem_per_set[i];

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx=malloc(tot_num_ss_elem*sizeof(int))))
  {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
 "Error: failed to allocate space for side set elem sort array for file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Sort side set element list into index array  - non-destructive */
  for (i=0;i<tot_num_ss_elem;i++)
    ss_elem_ndx[i] = i; /* init index array to current position */

  ex_iqsort(side_sets_elem_list, ss_elem_ndx,tot_num_ss_elem);


  /* Allocate space for the element block ids */
  if (!(elem_blk_ids=malloc(num_elem_blks*sizeof(int))))
  {
    free(ss_elem_ndx);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
        "Error: failed to allocate space for element block ids for file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_elem_blk_ids(exoid, elem_blk_ids))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    sprintf(errmsg,
           "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms=malloc(num_elem_blks*sizeof(struct elem_blk_parm))))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }
  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++)
  {
    /* read in an element block parameter */
    if ((ex_get_elem_block (exoid,
                            elem_blk_ids[i],
                            elem_type,
                            &num_elem_in_blk,
                            &num_nodes_per_elem,
                            &num_attr)) == -1)
    {
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      sprintf(errmsg,
             "Error: failed to get element block %d parameters in file id %d",
              elem_blk_ids[i], exoid);
      ex_err("ex_cvt_nodes_to_sides",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = num_elem_in_blk;
    elem_blk_parms[i].num_nodes_per_elem = num_nodes_per_elem;
    elem_blk_parms[i].num_attr = num_attr;

    for (m=0; m < (int)strlen(elem_type); m++)
      elem_blk_parms[i].elem_type[m] = (char)
              toupper((int)elem_type[m]);
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = CIRCLE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SPHERE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = QUAD;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TRIANGLE;
      /* determine side set node stride */
      if (ndim == 2)  /* 2d TRIs */
      {
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side[0] = 2;
        else 
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
      }
      else if (ndim == 3)  /* 3d TRIs */
      {
        elem_blk_parms[i].elem_type_val = TRISHELL;
        elem_blk_parms[i].num_nodes_per_side[0] =
          elem_blk_parms[i].num_nodes_per_elem;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SHELL;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
      {
        /* 2d SHELL; same as BEAM or TRUSS or BAR */
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].elem_type_val = BEAM;
      }
      else if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = HEX;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 9)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 12)  /* HEXSHELL */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 27)
        elem_blk_parms[i].num_nodes_per_side[0] = 9;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TETRA;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
      else if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = WEDGE;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 6)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
      sprintf(errmsg,
             "Warning: WEDGE%d is assumed to have %d nodes per face",
              elem_blk_parms[i].num_nodes_per_elem,
              elem_blk_parms[i].num_nodes_per_side[0]);
      ex_err("ex_cvt_nodes_to_sides",errmsg,EX_MSG);
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = PYRAMID;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
      sprintf(errmsg,
             "Warning: PYRAMID%d is assumed to have %d nodes per face",
              elem_blk_parms[i].num_nodes_per_elem,
              elem_blk_parms[i].num_nodes_per_side[0]);
      ex_err("ex_cvt_nodes_to_sides",errmsg,EX_MSG);
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = BEAM;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0)  ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
    {
      elem_blk_parms[i].elem_type_val = TRUSS;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = NULL_ELEMENT;
      /* set side set node stride */
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
    }
    else
    { /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = UNK;
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
    }
    elem_blk_parms[i].elem_blk_id = elem_blk_ids[i];    /* save id */
    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }


  /* Allocate space for the ss element to element block parameter index array */
  if (!(ss_parm_ndx=malloc(tot_num_ss_elem*sizeof(int))))
  {
    free(elem_blk_parms);
    free(elem_blk_ids);
    free(ss_elem_ndx);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
"Error: failed to allocate space for side set elem parms index for file id %d"
,
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }


  /* Allocate space for the ss element to node list index array */
  if (!(ss_elem_node_ndx=malloc((tot_num_ss_elem+1)*sizeof(int))))
  {
    free(ss_parm_ndx);
    free(elem_blk_parms);
    free(elem_blk_ids);
    free(ss_elem_ndx);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
"Error: failed to allocate space for side set elem to node index for file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }

/* determine if each side set has uniform element types; this will
   be used to help determine the stride through the node list
*/

  /* Allocate space for same element type flag array*/
  if (!(same_elem_type=malloc(num_side_sets*sizeof(int))))
  {
    free(ss_elem_ndx);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
   "Error: failed to allocate space for element type flag array for file id %d",
            exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return (EX_FATAL);
  }

  elem_ctr = num_elem_per_set[0];
  same_elem_type[0] = TRUE;
  for (i=0,k=0;i<tot_num_ss_elem;i++)
  {
    for (j=0; j<num_elem_blks; j++)
    {
      if (side_sets_elem_list[i] <= elem_blk_parms[j].elem_ctr) break;
    }

    if ( i == 0 ) {
      el_type = elem_blk_parms[j].elem_type_val;
    } 

    /* determine which side set this element is in; assign to kth side set */
    if ( i >= elem_ctr ) {
      elem_ctr += num_elem_per_set[++k];
      el_type = elem_blk_parms[j].elem_type_val;
      same_elem_type[k] = TRUE;
    }

    if (el_type != elem_blk_parms[j].elem_type_val) same_elem_type[k] = FALSE;

  }

/* Build side set element to node list index and side set element 
   parameter index.
*/
  node_ctr = 0;
  elem_ctr = num_elem_per_set[0];
  for (i=0,k=0;i<tot_num_ss_elem;i++)
  {
    for (j=0; j<num_elem_blks; j++)
    {
      if (side_sets_elem_list[i] <= elem_blk_parms[j].elem_ctr)
      {
        ss_parm_ndx[i] = j;     /* assign parameter block index */
        break;
      }
    }
    ss_elem_node_ndx[i] = node_ctr;     /* assign node list index */

    /* determine which side set this element is in; assign to kth side set */
    if (i >= elem_ctr) {
       /* skip over NULL side sets */
       while (num_elem_per_set[++k] == 0);
       elem_ctr += num_elem_per_set[k];
    }

    /* determine number of nodes per side */
    if (((num_nodes_per_set[k] % num_elem_per_set[k]) == 0) &&
         (same_elem_type[k])) {  /* all side set elements are same type */
       node_ctr += num_nodes_per_set[k] /num_elem_per_set[k];
    } else {
       node_ctr += elem_blk_parms[j].num_nodes_per_side[0];
    }
  }

  ss_elem_node_ndx[i] = node_ctr;       /* assign node list index */
  free(same_elem_type);
  
  /* All setup, ready to go ... */
  
  elem_ctr=0;

  for (j=0; j < tot_num_ss_elem; j++)
  {

    if (side_sets_elem_list[ss_elem_ndx[j]] > elem_ctr)
    {
      /* release connectivity array space and get next one */
      if (elem_ctr > 0)
        free(connect);

      /* Allocate space for the connectivity array for new element block */
      if (!(connect= 
             malloc(elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk*
                 elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem*
                                 sizeof(int))))
      {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
        "Error: failed to allocate space for connectivity array for file id %d",
                exoid);
        ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
        free(ss_elem_node_ndx);
        free(ss_parm_ndx);
        free(elem_blk_parms);
        free(elem_blk_ids);
        free(ss_elem_ndx);
        return (EX_FATAL);
      }

      /* get connectivity array */
      if (ex_get_elem_conn(
                        exoid,
                        elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                        connect) == -1)
      {
        sprintf(errmsg,
       "Error: failed to get connectivity array for elem blk %d for file id %d",
                elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                exoid);
        ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
        free(connect);
        free(ss_elem_node_ndx);
        free(ss_parm_ndx);
        free(elem_blk_parms);
        free(elem_blk_ids);
        free(ss_elem_ndx);
        return (EX_FATAL);
      }
      elem_ctr = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr;
    }
/*  For the first node of each side in side set, using a linear search 
      (of up to num_nodes_per_elem) of the connectivity array, 
      locate the node position in the element. The first node position
      and the second node position are used with a element type specific
      table to determine the side. */

    elem_num = side_sets_elem_list[ss_elem_ndx[j]]-1;/* element number 0-based*/
    /* calculate the relative element number position in it's block*/
    elem_num_pos = elem_num - 
                  (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr -
                   elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk);
    /* calculate the beginning of the node list for this element by
         using the ss_elem_node_ndx index into the side_sets_node_index
         and adding the element number position * number of nodes per elem */

    num_nodes_per_elem = 
               elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem;
    for (n=0; n<num_nodes_per_elem; n++)
    {
      /* find node in connectivity array that matches first node in side set */
      if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]] == 
          connect[num_nodes_per_elem*(elem_num_pos)+n])
      {
        switch (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type_val)
        {
          case CIRCLE:
          case SPHERE:
          {
            /* simple case: 1st node number is same as side # */
                side_sets_side_list[ss_elem_ndx[j]] = n+1;
            break;
          }
          case QUAD:
          case TRIANGLE:
          case TRUSS:
          case BEAM:
          {
            /* simple case: 1st node number is same as side # */
                side_sets_side_list[ss_elem_ndx[j]] = n+1;
            break;
          }
          case TRISHELL:
          {
            /* use table to find which node to compare to next */
            num_node_per_side = ss_elem_node_ndx[ss_elem_ndx[j]+1] - 
                                ss_elem_node_ndx[ss_elem_ndx[j]];

            if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (trishell_table[0][2*n]-1)]) 
            {
              /* Assume only front or back, no edges... */
              side_sets_side_list[ss_elem_ndx[j]] = trishell_table[1][2*n];
            }
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (trishell_table[0][2*n+1]-1)]) 
            {
              /* Assume only front or back, no edges... */
              side_sets_side_list[ss_elem_ndx[j]] = trishell_table[1][2*n+1];
            }
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (trishell_table[0][2*n+2]-1)]) 
            {
              /* Assume only front or back, no edges... */
              side_sets_side_list[ss_elem_ndx[j]] = trishell_table[1][2*n+2];
            }
            else
            { 
              exerrval = EX_BADPARAM;
              sprintf(errmsg,
                     "Error: failed to find TRIANGULAR SHELL element %d, node %d in connectivity array %d for file id %d",
                     side_sets_elem_list[ss_elem_ndx[j]],
                     side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1],
                     elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                     exoid);
              ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
              free(connect);
              free(ss_elem_node_ndx);
              free(ss_parm_ndx);
              free(elem_blk_parms);
              free(elem_blk_ids);
              free(ss_elem_ndx);
              return (EX_FATAL);
            }
            break;

          }
          case SHELL:
          {
            /* use table to find which node to compare to next */

            num_node_per_side = ss_elem_node_ndx[ss_elem_ndx[j]+1] - 
                                ss_elem_node_ndx[ss_elem_ndx[j]];

            if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (shell_table[0][2*n]-1)]) 
            {
              if (num_node_per_side >= 4)
                /* 4- or 8-node side (front or back face) */
                side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n];
              else
                /* 2- or 3-node side (edge of shell) */
                side_sets_side_list[ss_elem_ndx[j]] = shell_edge_table[1][2*n];
            }
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (shell_table[0][2*n+1]-1)]) 
            {
              if (num_node_per_side >= 4)
                /* 4- or 8-node side (front or back face) */
                side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n+1];
              else
                /* 2- or 3-node side (edge of shell) */
                side_sets_side_list[ss_elem_ndx[j]]=shell_edge_table[1][2*n+1];
            }
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] ==
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (shell_table[0][2*n+2]-1)]) 
            {
              if (num_node_per_side >= 4)
                /* 4- or 8-node side (front or back face) */
                side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n+2];
              else
                /* 2- or 3-node side (edge of shell) */
                side_sets_side_list[ss_elem_ndx[j]]=shell_edge_table[1][2*n+2];
            }
            else
            { 
              exerrval = EX_BADPARAM;
              sprintf(errmsg,
                     "Error: failed to find SHELL element %d, node %d in connectivity array %d for file id %d",
                     side_sets_elem_list[ss_elem_ndx[j]],
                     side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1],
                     elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                     exoid);
              ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
              free(connect);
              free(ss_elem_node_ndx);
              free(ss_parm_ndx);
              free(elem_blk_parms);
              free(elem_blk_ids);
              free(ss_elem_ndx);
              return (EX_FATAL);
            }
            break;

          }
          case HEX:
          {
            /* use table to find which node to compare to next */
          
            if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (hex_table[0][3*n]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (hex_table[0][3*n+1]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n+1];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (hex_table[0][3*n+2]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n+2];
            else
            {
              exerrval = EX_BADPARAM;
              sprintf(errmsg,
                     "Error: failed to find HEX element %d, node %d in connectivity array %d for file id %d",
                     side_sets_elem_list[ss_elem_ndx[j]],
                     side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1],
                     elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                     exoid);
              ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
              free(connect);
              free(ss_elem_node_ndx);
              free(ss_parm_ndx);
              free(elem_blk_parms);
              free(elem_blk_ids);
              free(ss_elem_ndx);
              return (EX_FATAL);
            }
            break;
          }
          case TETRA:
          {
            /* use table to find which node to compare to next */
          
            if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (tetra_table[0][3*n]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (tetra_table[0][3*n+1]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n+1];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (tetra_table[0][3*n+2]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n+2];
            else
            {
              exerrval = EX_BADPARAM;
              sprintf(errmsg,
                     "Error: failed to find TETRA element %d, node %d in connectivity array %d for file id %d",
                     side_sets_elem_list[ss_elem_ndx[j]],
                     side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1],
                     elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                     exoid);
              ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
              free(connect);
              free(ss_elem_node_ndx);
              free(ss_parm_ndx);
              free(elem_blk_parms);
              free(elem_blk_ids);
              free(ss_elem_ndx);
              return (EX_FATAL);
            }
            break;
          }
          case PYRAMID:
          {
 /* NOTE: PYRAMID elements in side set node lists are currently not supported */
            exerrval = EX_BADPARAM;
            sprintf(errmsg,
  "ERROR: unsupported PYRAMID element found in side set node list in file id %d",
                    exoid);
            ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
            free(connect);
            free(ss_elem_node_ndx);
            free(ss_parm_ndx);
            free(elem_blk_parms);
            free(elem_blk_ids);
            free(ss_elem_ndx);
            return (EX_FATAL);
          }
          case WEDGE:
          {
#if 1
 /* NOTE: WEDGE elements in side set node lists are currently not supported */
            exerrval = EX_BADPARAM;
            sprintf(errmsg,
  "ERROR: unsupported WEDGE element found in side set node list in file id %d",
                    exoid);
            ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
            free(connect);
            free(ss_elem_node_ndx);
            free(ss_parm_ndx);
            free(elem_blk_parms);
            free(elem_blk_ids);
            free(ss_elem_ndx);
            return (EX_FATAL);

#else
            /* use wedge_table to find which node to compare to next */
          
/* This section is commented out because Wedges are no longer supported !!!*/

            if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (wedge_table[0][3*n]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (wedge_table[0][3*n+1]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n+1];
            else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == 
                connect[num_nodes_per_elem*(elem_num_pos)+
                        (wedge_table[0][3*n+2]-1)])
              side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n+2];
            else
            {
              exerrval = EX_BADPARAM;
              sprintf(errmsg,
                     "Error: failed to find WEDGE element %d, node %d in connectivity array %d for file id %d",
                     side_sets_elem_list[ss_elem_ndx[j]],
                     side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1],
                     elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                     exoid);
              ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
              free(connect);
              free(ss_elem_node_ndx);
              free(ss_parm_ndx);
              free(elem_blk_parms);
              free(elem_blk_ids);
              free(ss_elem_ndx);
              return (EX_FATAL);
            }
            break;
#endif
          }
          default:
          {
            exerrval = EX_BADPARAM;
            sprintf(errmsg,
                   "Error: %s is an unsupported element type",
                    elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type);
            ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
            return(EX_FATAL);
          }
        }
        break; /* done with this element */
      }
    }
    if (n >= num_nodes_per_elem) /* did we find the node? */
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: failed to find element %d, node %d in element block %d for file id %d",
              side_sets_elem_list[ss_elem_ndx[j]],
              side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]],
              elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
              exoid);
      ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
      free(connect);
      free(ss_elem_node_ndx);
      free(ss_parm_ndx);
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      return (EX_FATAL);
    }

  }

  /* All done: release connectivity array space, element block ids array,
     element block parameters array, and side set element index array */
  free(connect);
  free(ss_elem_node_ndx);
  free(ss_parm_ndx);
  free(elem_blk_parms);
  free(elem_blk_ids);
  free(ss_elem_ndx);

  return (EX_NOERR);
}
Beispiel #2
0
int ex_get_side_set_node_count(int exoid,
                               int side_set_id,
                               int *side_set_node_cnt_list)
{
  int ii, i, j, m; 
  int  num_side_sets, num_elem_blks, num_df, ndim;
  int tot_num_elem = 0, tot_num_ss_elem = 0, side, elem;
  int *elem_blk_ids;
  int *ss_elem_ndx;
  int *side_set_elem_list, *side_set_side_list;
  int elem_ctr;
  int num_elem_in_blk, num_nodes_per_elem, num_attr;
  float fdum;
  char *cdum, elem_type[MAX_STR_LENGTH+1];

  struct elem_blk_parm
  {
    char elem_type[MAX_STR_LENGTH+1];
    int elem_blk_id;
    int num_elem_in_blk;
    int num_nodes_per_elem;
    int num_sides;
    int num_nodes_per_side[6];
    int num_attr;
    int elem_ctr;
    int elem_type_val;
  } *elem_blk_parms;

  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  cdum = 0; /* initialize even though it is not used */

  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */
  if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0)
  {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_get_side_set_node_count",errmsg,EX_WARN);
    return(EX_WARN);
  }

  /* Lookup index of side set id in VAR_SS_IDS array */
  ex_id_lkup(exoid,VAR_SS_IDS,side_set_id);
  if (exerrval != 0) 
  {
     if (exerrval == EX_NULLENTITY)
     {
       sprintf(errmsg,
              "Warning: side set %d is NULL in file id %d",
               side_set_id,exoid);
       ex_err("ex_get_side_set_node_count",errmsg,EX_MSG);
       return (EX_WARN);
     }
     else
     {

     sprintf(errmsg,
     "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d",
             side_set_id,exoid);
     ex_err("ex_get_side_set_node_count",errmsg,exerrval);
     return (EX_FATAL);
     }
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */
  if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* First determine the  # of elements in the side set*/
  if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1)
  {
    sprintf(errmsg,
         "Error: failed to get number of elements in side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* Allocate space for the side set element list */
  if (!(side_set_elem_list=malloc(tot_num_ss_elem*sizeof(int))))
  {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set element list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set side list */
  if (!(side_set_side_list=malloc(tot_num_ss_elem*sizeof(int))))
  {
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set side list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_side_set(exoid, side_set_id, 
                      side_set_elem_list, side_set_side_list) == -1)
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    sprintf(errmsg,
    "Error: failed to get side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx=malloc(tot_num_ss_elem*sizeof(int))))
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
            "Error: failed to allocate space for side set elem sort array for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Sort side set element list into index array  - non-destructive */
  for (i=0;i<tot_num_ss_elem;i++) {
    ss_elem_ndx[i] = i; /* init index array to current position */
  }
  ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);


  /* Allocate space for the element block ids */
  if (!(elem_blk_ids=malloc(num_elem_blks*sizeof(int))))
  {
    exerrval = EX_MEMFAIL;
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
            "Error: failed to allocate space for element block ids for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_elem_blk_ids(exoid, elem_blk_ids) == -1)
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
            "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms=malloc(num_elem_blks*sizeof(struct elem_blk_parm))))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_count",errmsg,exerrval);
    return (EX_FATAL);
  }

  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++)
  {
    /* read in an element block parameter */
    if ((ex_get_elem_block (exoid, elem_blk_ids[i], elem_type, &num_elem_in_blk,
                            &num_nodes_per_elem, &num_attr)) == -1) {
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      sprintf(errmsg,
             "Error: failed to get element block %d parameters in file id %d",
              elem_blk_ids[i], exoid);
      ex_err("ex_get_side_set_node_count",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = num_elem_in_blk;
    elem_blk_parms[i].num_nodes_per_elem = num_nodes_per_elem;
    elem_blk_parms[i].num_attr = num_attr;

    for (m=0; (size_t)m < strlen(elem_type); m++) {
      elem_blk_parms[i].elem_type[m] = (char)toupper((int)elem_type[m]);
    }
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = CIRCLE;
      elem_blk_parms[i].num_sides = 1;
      elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SPHERE;
      elem_blk_parms[i].num_sides = 1;
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = QUAD;
      elem_blk_parms[i].num_sides = 4;
      if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 5) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 9 ||
                 elem_blk_parms[i].num_nodes_per_elem == 8) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TRIANGLE;
      if (ndim == 2) { /* 2d TRIs */
        elem_blk_parms[i].num_sides = 3;
        if (elem_blk_parms[i].num_nodes_per_elem == 3) {
          elem_blk_parms[i].num_nodes_per_side[0] = 2;
          elem_blk_parms[i].num_nodes_per_side[1] = 2;
          elem_blk_parms[i].num_nodes_per_side[2] = 2;
        } else if (elem_blk_parms[i].num_nodes_per_elem == 6) {
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
          elem_blk_parms[i].num_nodes_per_side[1] = 3;
          elem_blk_parms[i].num_nodes_per_side[2] = 3;
        }
      } else if (ndim == 3) { /* 3d TRIs -- triangular shell*/
        elem_blk_parms[i].num_sides = 5; /* 2 Faces and 3 Edges */
        if (elem_blk_parms[i].num_nodes_per_elem == 3) {
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
          elem_blk_parms[i].num_nodes_per_side[1] = 3;
          elem_blk_parms[i].num_nodes_per_side[2] = 2;
          elem_blk_parms[i].num_nodes_per_side[3] = 2;
          elem_blk_parms[i].num_nodes_per_side[4] = 2;
        } else if (elem_blk_parms[i].num_nodes_per_elem == 6) {
          elem_blk_parms[i].num_nodes_per_side[0] = 6;
          elem_blk_parms[i].num_nodes_per_side[1] = 6;
          elem_blk_parms[i].num_nodes_per_side[2] = 3;
          elem_blk_parms[i].num_nodes_per_side[3] = 3;
          elem_blk_parms[i].num_nodes_per_side[4] = 3;
        } else {
          EL_NODE_COUNT_ERROR;
        }
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SHELL;

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {/* KLUDGE for 2D Shells*/
        elem_blk_parms[i].num_sides = 2; 
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_sides = 6;  /* 2 Faces, 4 Edges */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
        elem_blk_parms[i].num_nodes_per_side[4] = 2;
        elem_blk_parms[i].num_nodes_per_side[5] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 8 ||
                 elem_blk_parms[i].num_nodes_per_elem == 9) {
        elem_blk_parms[i].num_sides = 6;  /* 2 Faces, 4 Edges */
        elem_blk_parms[i].num_nodes_per_side[0] =
          elem_blk_parms[i].num_nodes_per_elem; /* 8 or 9 */
        elem_blk_parms[i].num_nodes_per_side[1] =
          elem_blk_parms[i].num_nodes_per_elem; /* 8 or 9 */
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 3;
        elem_blk_parms[i].num_nodes_per_side[5] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = HEX;
      elem_blk_parms[i].num_sides = 6;  
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8) {  /* 8-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 9) { /* 9-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 12) { /* HEXSHELLS */
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 20) { /* 20-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
        elem_blk_parms[i].num_nodes_per_side[1] = 8;
        elem_blk_parms[i].num_nodes_per_side[2] = 8;
        elem_blk_parms[i].num_nodes_per_side[3] = 8;
        elem_blk_parms[i].num_nodes_per_side[4] = 8;
        elem_blk_parms[i].num_nodes_per_side[5] = 8;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 27) { /* 27-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 9;
        elem_blk_parms[i].num_nodes_per_side[1] = 9;
        elem_blk_parms[i].num_nodes_per_side[2] = 9;
        elem_blk_parms[i].num_nodes_per_side[3] = 9;
        elem_blk_parms[i].num_nodes_per_side[4] = 9;
        elem_blk_parms[i].num_nodes_per_side[5] = 9;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TETRA;
      elem_blk_parms[i].num_sides = 4;  
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 8) {
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 10) {
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = WEDGE;
      elem_blk_parms[i].num_sides = 5;  
      if (elem_blk_parms[i].num_nodes_per_elem == 6) {
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 3;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 15){
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
        elem_blk_parms[i].num_nodes_per_side[1] = 8;
        elem_blk_parms[i].num_nodes_per_side[2] = 8;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 6;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = PYRAMID;
      elem_blk_parms[i].num_sides = 5;  
      if (elem_blk_parms[i].num_nodes_per_elem == 5) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 13){
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 8;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = BEAM;
      elem_blk_parms[i].num_sides = 2;  

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 3){
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
    {
      elem_blk_parms[i].elem_type_val = TRUSS;
      elem_blk_parms[i].num_sides = 2;  

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 3) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    /* Used for an empty block in a parallel decomposition */
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0) {
      elem_blk_parms[i].elem_type_val = '\0';
      elem_blk_parms[i].num_sides = 0;  
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
      elem_blk_parms[i].num_elem_in_blk = 0;
    } else {
      /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = UNK;
      elem_blk_parms[i].num_sides = 0;  
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
    }

    elem_blk_parms[i].elem_blk_id = elem_blk_ids[i];    /* save id */
    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }


  /* Finally... Create the list of node counts for each face in the
   * side set.
   */

  j = 0; /* The current element block... */
  for (ii=0;ii<tot_num_ss_elem;ii++) {

    i = ss_elem_ndx[ii];
    elem = side_set_elem_list[i];
    side = side_set_side_list[i]-1; /* Convert to 0-based sides */

    /*
     * Since the elements are being accessed in sorted, order, the
     * block that contains the elements must progress sequentially
     * from block 0 to block[num_elem_blks-1]. Once we find an element
     * not in this block, find a following block that contains it...
     */       
    for ( ; j<num_elem_blks; j++) {
      if (elem <= elem_blk_parms[j].elem_ctr) {
        break;
      }
    }

    if (j < num_elem_blks) {
      assert(side < elem_blk_parms[j].num_sides);  
      side_set_node_cnt_list[i] = elem_blk_parms[j].num_nodes_per_side[side];
    } else {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: Invalid element number %d found in side set %d in file %d",
              side_set_elem_list[i], side_set_id, exoid);
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      ex_err("ex_get_side_set_node_count",errmsg,EX_MSG);
      return (EX_FATAL);
    }
  }

  /* All done: release connectivity array space, element block ids
   * array, element block parameters array, and side set element index
   * array
   */
  free(elem_blk_ids);
  free(elem_blk_parms);
  free(ss_elem_ndx);
  free(side_set_side_list);
  free(side_set_elem_list);

  return(EX_NOERR);
}
int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_nodes_per_set,
                          void_int *side_sets_elem_index, /* unused */
                          void_int *side_sets_node_index, /* unused */
                          void_int *side_sets_elem_list, void_int *side_sets_node_list,
                          void_int *side_sets_side_list)
{
  size_t    i, j, k, n;
  int       num_side_sets, num_elem_blks;
  int64_t   tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0, ndim;
  void_int *elem_blk_ids     = NULL;
  void_int *connect          = NULL;
  void_int *ss_elem_ndx      = NULL;
  void_int *ss_elem_node_ndx = NULL;
  void_int *ss_parm_ndx      = NULL;
  size_t    elem_ctr, node_ctr, elem_num_pos;
  int       num_nodes_per_elem, num_node_per_side;

  int *same_elem_type = NULL;
  int  el_type        = 0;

  int int_size;
  int ids_size;

  struct elem_blk_parm *elem_blk_parms = NULL;

  int err_stat = EX_NOERR;

  /* node to side translation tables -
     These tables are used to look up the side number based on the
     first and second node in the side/face list. The side node order
     is found in the original Exodus document, SAND87-2997. The element
     node order is found in the ExodusII document, SAND92-2137. These
     tables were generated by following the right-hand rule for determining
     the outward normal. Note: Only the more complex 3-D shapes require
     these tables, the simple shapes are trivial - the first node found
     is also the side number.
  */

  /*    1     2   3    4                                          node 1 */
  static int shell_table[2][8] = {
      {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */
      {1, 2, 1, 2, 1, 2, 1, 2}  /* side # */
  };

  /*    1     2   3    4                                          node 1 */
  static int shell_edge_table[2][8] = {
      {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */
      {3, 6, 4, 3, 5, 4, 6, 5}  /* side # */
  };

  /*    1     2   3                                               node 1 */
  static int trishell_table[2][6] = {
      {2, 3, 3, 1, 1, 2}, /* node 2 */
      {1, 2, 1, 2, 1, 2}  /* side # */
  };

  /*     1      2      3      4                                   node 1 */
  static int tetra_table[2][12] = {
      {2, 3, 4, 1, 3, 4, 4, 1, 2, 1, 2, 3}, /* node 2 */
      {1, 4, 3, 4, 2, 1, 2, 3, 4, 1, 2, 3}  /* side # */
  };

#if 0
  static int wedge_table[2][18]  = {
    /*     1      2      3      4      5      6                     node 1 */
    {2,4,3, 5,1,3, 6,1,2, 1,6,5, 6,2,4, 4,3,5},              /* node 2 */
    {1,3,4, 1,4,2, 2,3,4, 1,3,5, 5,2,1, 5,3,2}               /* side # */
  };
#endif

  static int hex_table[2][24] = {
      /*     1      2      3      4      5      6      7      8       node 1 */
      {4, 2, 5, 1, 3, 6, 7, 4, 2, 3, 1, 8, 6, 8, 1, 5, 2, 7, 8, 6, 3, 7, 5, 4}, /* node 2 */
      {5, 1, 4, 5, 2, 1, 2, 3, 5, 5, 4, 3, 6, 4, 1, 1, 2, 6, 6, 2, 3, 3, 6, 4}  /* side # */
  };

  char errmsg[MAX_ERR_LENGTH];

  ex_check_valid_file_id(exoid);

  exerrval = 0; /* clear error code */

  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */

  num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
  if (num_side_sets < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    return (EX_FATAL);
  }

  if (num_side_sets == 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no side sets defined in file id %d", exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, EX_WARN);
    return (EX_WARN);
  }

  num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
  if (num_elem_blks < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of element blocks in file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    return (EX_FATAL);
  }

  tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
  if (tot_num_elem < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get total number of elements in file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */
  ndim = ex_inquire_int(exoid, EX_INQ_DIM);

  int_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    int_size = sizeof(int64_t);
  }

  /* First count up # of elements in the side sets*/
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    for (i = 0; i < num_side_sets; i++) {
      tot_num_ss_elem += ((int64_t *)num_elem_per_set)[i];
    }
  }
  else {
    for (i = 0; i < num_side_sets; i++) {
      tot_num_ss_elem += ((int *)num_elem_per_set)[i];
    }
  }

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem sort "
                                     "array for file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  if (int_size == sizeof(int64_t)) {
    /* Sort side set element list into index array  - non-destructive */
    int64_t *elems = (int64_t *)ss_elem_ndx;
    for (i = 0; i < tot_num_ss_elem; i++) {
      elems[i] = i; /* init index array to current position */
    }
    ex_iqsort64(side_sets_elem_list, elems, tot_num_ss_elem);
  }
  else {
    /* Sort side set element list into index array  - non-destructive */
    int *elems = (int *)ss_elem_ndx;
    for (i = 0; i < tot_num_ss_elem; i++) {
      elems[i] = i; /* init index array to current position */
    }
    ex_iqsort(side_sets_elem_list, elems, tot_num_ss_elem);
  }

  /* Allocate space for the element block ids */
  ids_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
    ids_size = sizeof(int64_t);
  }

  if (!(elem_blk_ids = malloc(num_elem_blks * ids_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to allocate space for element block ids for file id %d", exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids)) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get element block ids in file id %d", exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, EX_MSG);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Allocate space for the element block params */
  if (!(elem_blk_parms = malloc(num_elem_blks * sizeof(struct elem_blk_parm)))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for element block params "
                                     "for file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }
  elem_ctr = 0;
  for (i = 0; i < num_elem_blks; i++) {
    ex_entity_id id;
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      id = ((int64_t *)elem_blk_ids)[i];
    }
    else {
      id = ((int *)elem_blk_ids)[i];
    }

    err_stat = ex_int_get_block_param(exoid, id, ndim, &elem_blk_parms[i]);
    if (err_stat != EX_NOERR) {
      goto cleanup;
    }

    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr; /* save elem number max */
  }

  /* Allocate space for the ss element to element block parameter index array */
  if (!(ss_parm_ndx = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem parms "
                                     "index for file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Allocate space for the ss element to node list index array */
  if (!(ss_elem_node_ndx = malloc((tot_num_ss_elem + 1) * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem to node "
                                     "index for file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* determine if each side set has uniform element types; this will
     be used to help determine the stride through the node list
  */

  /* Allocate space for same element type flag array*/
  if (!(same_elem_type = malloc(num_side_sets * sizeof(int)))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for element type flag "
                                     "array for file id %d",
             exoid);
    ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  same_elem_type[0] = EX_TRUE;
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    elem_ctr = ((int64_t *)num_elem_per_set)[0];
    for (i = 0, k = 0; i < tot_num_ss_elem; i++) {
      int64_t elem = ((int64_t *)side_sets_elem_list)[i];
      for (j = 0; j < num_elem_blks; j++) {
        if (elem <= elem_blk_parms[j].elem_ctr) {
          break;
        }
      }

      if (j >= num_elem_blks) {
        exerrval = EX_INTERNAL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: internal logic error for file id %d", exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      if (i == 0) {
        el_type = elem_blk_parms[j].elem_type_val;
      }

      /* determine which side set this element is in; assign to kth side set */
      if (i >= elem_ctr) {
        elem_ctr += ((int64_t *)num_elem_per_set)[++k];

        el_type           = elem_blk_parms[j].elem_type_val;
        same_elem_type[k] = EX_TRUE;
      }

      if (el_type != elem_blk_parms[j].elem_type_val) {
        same_elem_type[k] = EX_FALSE;
      }
    }

    /* Build side set element to node list index and side set element
       parameter index.
    */
    node_ctr = 0;
    elem_ctr = ((int64_t *)num_elem_per_set)[0];
    for (i = 0, k = 0; i < tot_num_ss_elem; i++) {
      int64_t elem = ((int64_t *)side_sets_elem_list)[i];

      for (j = 0; j < num_elem_blks; j++) {
        if (elem <= elem_blk_parms[j].elem_ctr) {
          break;
        }
      }
      if (j >= num_elem_blks) {
        exerrval = EX_INTERNAL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: internal logic error for file id %d", exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      ((int64_t *)ss_parm_ndx)[i]      = j;        /* assign parameter block index */
      ((int64_t *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */

      /* determine which side set this element is in; assign to kth side set */
      if (i >= elem_ctr) {
        /* skip over NULL side sets */
        while (((int64_t *)num_elem_per_set)[++k] == 0) {
          ;
        }
        elem_ctr += ((int64_t *)num_elem_per_set)[k];
      }

      /* determine number of nodes per side */
      if (((((int64_t *)num_nodes_per_set)[k] % ((int64_t *)num_elem_per_set)[k]) == 0) &&
          (same_elem_type[k] == EX_TRUE)) { /* all side set elements are same type */
        node_ctr += ((int64_t *)num_nodes_per_set)[k] / ((int64_t *)num_elem_per_set)[k];
      }
      else {
        node_ctr += elem_blk_parms[j].num_nodes_per_side[0];
      }
    }
    ((int64_t *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */
  }
  else {
    elem_ctr = ((int *)num_elem_per_set)[0];
    for (i = 0, k = 0; i < tot_num_ss_elem; i++) {
      int elem = ((int *)side_sets_elem_list)[i];

      for (j = 0; j < num_elem_blks; j++) {
        if (elem <= elem_blk_parms[j].elem_ctr) {
          break;
        }
      }

      if (j >= num_elem_blks) {
        exerrval = EX_INTERNAL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: internal logic error for file id %d", exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      if (i == 0) {
        el_type = elem_blk_parms[j].elem_type_val;
      }

      /* determine which side set this element is in; assign to kth side set */
      if (i >= elem_ctr) {
        elem_ctr += ((int *)num_elem_per_set)[++k];

        el_type           = elem_blk_parms[j].elem_type_val;
        same_elem_type[k] = EX_TRUE;
      }

      if (el_type != elem_blk_parms[j].elem_type_val) {
        same_elem_type[k] = EX_FALSE;
      }
    }

    /* Build side set element to node list index and side set element
       parameter index.
    */
    node_ctr = 0;
    elem_ctr = ((int *)num_elem_per_set)[0];
    for (i = 0, k = 0; i < tot_num_ss_elem; i++) {
      int elem = ((int *)side_sets_elem_list)[i];

      for (j = 0; j < num_elem_blks; j++) {
        if (elem <= elem_blk_parms[j].elem_ctr) {
          break;
        }
      }
      if (j >= num_elem_blks) {
        exerrval = EX_INTERNAL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: internal logic error for file id %d", exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      ((int *)ss_parm_ndx)[i]      = j;        /* assign parameter block index */
      ((int *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */

      /* determine which side set this element is in; assign to kth side set */
      if (i >= elem_ctr) {
        /* skip over NULL side sets */
        while (((int *)num_elem_per_set)[++k] == 0) {
          ;
        }
        elem_ctr += ((int *)num_elem_per_set)[k];
      }

      /* determine number of nodes per side */
      if (((((int *)num_nodes_per_set)[k] % ((int *)num_elem_per_set)[k]) == 0) &&
          (same_elem_type[k])) { /* all side set elements are same type */
        node_ctr += ((int *)num_nodes_per_set)[k] / ((int *)num_elem_per_set)[k];
      }
      else {
        node_ctr += elem_blk_parms[j].num_nodes_per_side[0];
      }
    }
    ((int *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */
  }

  /* All setup, ready to go ... */

  elem_ctr = 0;

  for (j = 0; j < tot_num_ss_elem; j++) {
    int64_t elem;
    int64_t idx;
    int64_t ss_node0, ss_node1;
    int64_t p_ndx;
    if (int_size == sizeof(int64_t)) {
      idx      = ((int64_t *)ss_elem_ndx)[j];
      elem     = ((int64_t *)side_sets_elem_list)[idx];
      ss_node0 = ((int64_t *)side_sets_node_list)[((int64_t *)ss_elem_node_ndx)[idx]];
      ss_node1 = ((int64_t *)side_sets_node_list)[((int64_t *)ss_elem_node_ndx)[idx] + 1];
      p_ndx    = ((int64_t *)ss_parm_ndx)[idx];
    }
    else {
      idx      = ((int *)ss_elem_ndx)[j];
      elem     = ((int *)side_sets_elem_list)[idx];
      ss_node0 = ((int *)side_sets_node_list)[((int *)ss_elem_node_ndx)[idx]];
      ss_node1 = ((int *)side_sets_node_list)[((int *)ss_elem_node_ndx)[idx] + 1];
      p_ndx    = ((int *)ss_parm_ndx)[idx];
    }
    elem_num = elem - 1;

    if (elem > elem_ctr) {
      /* release connectivity array space and get next one */
      if (elem_ctr > 0) {
        free(connect);
      }

      /* Allocate space for the connectivity array for new element block */
      if (!(connect = malloc(elem_blk_parms[p_ndx].num_elem_in_blk *
                             elem_blk_parms[p_ndx].num_nodes_per_elem * int_size))) {
        exerrval = EX_MEMFAIL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for connectivity "
                                         "array for file id %d",
                 exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      /* get connectivity array */
      if (ex_get_conn(exoid, EX_ELEM_BLOCK, elem_blk_parms[p_ndx].elem_blk_id, connect, NULL,
                      NULL) == -1) {
        snprintf(errmsg, MAX_ERR_LENGTH,
                 "ERROR: failed to get connectivity array for elem blk %" PRId64 " for file id %d",
                 elem_blk_parms[p_ndx].elem_blk_id, exoid);
        ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }
      elem_ctr = elem_blk_parms[p_ndx].elem_ctr;
    }
    /*  For the first node of each side in side set, using a linear search
        (of up to num_nodes_per_elem) of the connectivity array,
        locate the node position in the element. The first node position
        and the second node position are used with a element type specific
        table to determine the side. */

    if (connect == NULL) {
      snprintf(errmsg, MAX_ERR_LENGTH,
               "ERROR: logic error. Connect pointer is null for elem blk %" PRId64
               " for file id %d",
               elem_blk_parms[p_ndx].elem_blk_id, exoid);
      ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    /* calculate the relative element number position in it's block*/
    elem_num_pos =
        elem_num - (elem_blk_parms[p_ndx].elem_ctr - elem_blk_parms[p_ndx].num_elem_in_blk);
    /* calculate the beginning of the node list for this element by
       using the ss_elem_node_ndx index into the side_sets_node_index
       and adding the element number position * number of nodes per elem */

    num_nodes_per_elem = elem_blk_parms[p_ndx].num_nodes_per_elem;

    for (n = 0; n < num_nodes_per_elem; n++) {
      /* find node in connectivity array that matches first node in side set */
      if (((int_size == sizeof(int64_t)) &&
           (ss_node0 == ((int64_t *)connect)[num_nodes_per_elem * (elem_num_pos) + n])) ||
          ((int_size == sizeof(int)) &&
           (ss_node0 == ((int *)connect)[num_nodes_per_elem * (elem_num_pos) + n]))) {
        switch (elem_blk_parms[p_ndx].elem_type_val) {
        case EX_EL_CIRCLE:
        case EX_EL_SPHERE: {
          /* simple case: 1st node number is same as side # */
          put_side(side_sets_side_list, idx, n + 1, int_size);
          break;
        }
        case EX_EL_QUAD:
        case EX_EL_TRIANGLE:
        case EX_EL_TRUSS:
        case EX_EL_BEAM: {
          /* simple case: 1st node number is same as side # */
          put_side(side_sets_side_list, idx, n + 1, int_size);
          break;
        }
        case EX_EL_TRISHELL: {
          /* use table to find which node to compare to next */
          if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                (trishell_table[0][2 * n] - 1),
                                   int_size)) {
            /* Assume only front or back, no edges... */
            put_side(side_sets_side_list, idx, trishell_table[1][2 * n], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (trishell_table[0][2 * n + 1] - 1),
                                        int_size)) {
            /* Assume only front or back, no edges... */
            put_side(side_sets_side_list, idx, trishell_table[1][2 * n + 1], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (trishell_table[0][2 * n + 2] - 1),
                                        int_size)) {
            /* Assume only front or back, no edges... */
            put_side(side_sets_side_list, idx, trishell_table[1][2 * n + 2], int_size);
          }
          else {
            exerrval = EX_BADPARAM;
            snprintf(errmsg, MAX_ERR_LENGTH,
                     "ERROR: failed to find TRIANGULAR SHELL element %" PRId64 ", node %" PRId64
                     " in connectivity array %" PRId64 " for file id %d",
                     elem_num + 1, ss_node1, elem_blk_parms[p_ndx].elem_blk_id, exoid);
            ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
            err_stat = EX_FATAL;
            goto cleanup;
          }
          break;
        }
        case EX_EL_SHELL: {
          /* use table to find which node to compare to next */

          if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
            num_node_per_side =
                ((int64_t *)ss_elem_node_ndx)[idx + 1] - ((int64_t *)ss_elem_node_ndx)[idx];
          }
          else {
            num_node_per_side = ((int *)ss_elem_node_ndx)[idx + 1] - ((int *)ss_elem_node_ndx)[idx];
          }

          if (ss_node1 ==
              get_node(connect, num_nodes_per_elem * (elem_num_pos) + (shell_table[0][2 * n] - 1),
                       int_size)) {
            if (num_node_per_side >= 4) {
              /* 4- or 8-node side (front or back face) */
              put_side(side_sets_side_list, idx, shell_table[1][2 * n], int_size);
            }
            else {
              /* 2- or 3-node side (edge of shell) */
              put_side(side_sets_side_list, idx, shell_edge_table[1][2 * n], int_size);
            }
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (shell_table[0][2 * n + 1] - 1),
                                        int_size)) {
            if (num_node_per_side >= 4) {
              /* 4- or 8-node side (front or back face) */
              put_side(side_sets_side_list, idx, shell_table[1][2 * n + 1], int_size);
            }
            else {
              /* 2- or 3-node side (edge of shell) */
              put_side(side_sets_side_list, idx, shell_edge_table[1][2 * n + 1], int_size);
            }
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (shell_table[0][2 * n + 2] - 1),
                                        int_size)) {
            if (num_node_per_side >= 4) {
              /* 4- or 8-node side (front or back face) */
              put_side(side_sets_side_list, idx, shell_table[1][2 * n + 2], int_size);
            }
            else {
              /* 2- or 3-node side (edge of shell) */
              put_side(side_sets_side_list, idx, shell_edge_table[1][2 * n + 2], int_size);
            }
          }
          else {
            exerrval = EX_BADPARAM;
            snprintf(errmsg, MAX_ERR_LENGTH,
                     "ERROR: failed to find SHELL element %" PRId64 ", node %" PRId64
                     " in connectivity array %" PRId64 " for file id %d",
                     elem_num + 1, ss_node1, elem_blk_parms[p_ndx].elem_blk_id, exoid);
            ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
            err_stat = EX_FATAL;
            goto cleanup;
          }
          break;
        }
        case EX_EL_HEX: {
          /* use table to find which node to compare to next */

          if (ss_node1 == get_node(connect,
                                   num_nodes_per_elem * (elem_num_pos) + (hex_table[0][3 * n] - 1),
                                   int_size)) {
            put_side(side_sets_side_list, idx, hex_table[1][3 * n], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (hex_table[0][3 * n + 1] - 1),
                                        int_size)) {
            put_side(side_sets_side_list, idx, hex_table[1][3 * n + 1], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (hex_table[0][3 * n + 2] - 1),
                                        int_size)) {
            put_side(side_sets_side_list, idx, hex_table[1][3 * n + 2], int_size);
          }
          else {
            exerrval = EX_BADPARAM;
            snprintf(errmsg, MAX_ERR_LENGTH,
                     "ERROR: failed to find HEX element %" PRId64 ", node %" PRId64
                     " in connectivity array %" PRId64 " for file id %d",
                     elem_num + 1, ss_node1, elem_blk_parms[p_ndx].elem_blk_id, exoid);
            ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
            err_stat = EX_FATAL;
            goto cleanup;
          }
          break;
        }
        case EX_EL_TETRA: {
          /* use table to find which node to compare to next */

          if (ss_node1 ==
              get_node(connect, num_nodes_per_elem * (elem_num_pos) + (tetra_table[0][3 * n] - 1),
                       int_size)) {
            put_side(side_sets_side_list, idx, tetra_table[1][3 * n], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (tetra_table[0][3 * n + 1] - 1),
                                        int_size)) {
            put_side(side_sets_side_list, idx, tetra_table[1][3 * n + 1], int_size);
          }
          else if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) +
                                                     (tetra_table[0][3 * n + 2] - 1),
                                        int_size)) {
            put_side(side_sets_side_list, idx, tetra_table[1][3 * n + 2], int_size);
          }
          else {
            exerrval = EX_BADPARAM;
            snprintf(errmsg, MAX_ERR_LENGTH,
                     "ERROR: failed to find TETRA element %" PRId64 ", node %" PRId64
                     " in connectivity array %" PRId64 " for file id %d",
                     elem_num + 1, ss_node1, elem_blk_parms[p_ndx].elem_blk_id, exoid);
            ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
            err_stat = EX_FATAL;
            goto cleanup;
          }
          break;
        }
        case EX_EL_PYRAMID: {
          /* NOTE: PYRAMID elements in side set node lists are currently not
           * supported */
          exerrval = EX_BADPARAM;
          snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: unsupported PYRAMID element found in side "
                                           "set node list in file id %d",
                   exoid);
          ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
          err_stat = EX_FATAL;
          goto cleanup;
        }
        case EX_EL_WEDGE: {
          /* NOTE: WEDGE elements in side set node lists are currently not
           * supported */
          exerrval = EX_BADPARAM;
          snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: unsupported WEDGE element found in side set "
                                           "node list in file id %d",
                   exoid);
          ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
          err_stat = EX_FATAL;
          goto cleanup;
        }
        default: {
          exerrval = EX_BADPARAM;
          snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: %s is an unsupported element type",
                   elem_blk_parms[p_ndx].elem_type);
          ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
          err_stat = EX_FATAL;
          goto cleanup;
        }
        }
        break; /* done with this element */
      }
    }
    if (n >= num_nodes_per_elem) /* did we find the node? */
    {
      exerrval = EX_BADPARAM;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to find element %" PRId64 ", node %" PRId64
                                       " in element block %" PRId64 " for file id %d",
               elem_num + 1, ss_node0, elem_blk_parms[p_ndx].elem_blk_id, exoid);
      ex_err("ex_cvt_nodes_to_sides", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }
  }

/* All done: release connectivity array space, element block ids array,
   element block parameters array, and side set element index array */
cleanup:
  free(connect);
  free(ss_elem_node_ndx);
  free(ss_parm_ndx);
  free(elem_blk_parms);
  free(elem_blk_ids);
  free(ss_elem_ndx);
  free(same_elem_type);

  return (err_stat);
}
int ex_get_side_set_node_count(int exoid, ex_entity_id side_set_id, int *side_set_node_cnt_list)
{
  int       ii, i, j;
  int       num_side_sets, num_elem_blks, ndim;
  size_t    tot_num_ss_elem = 0;
  int64_t   side, elem;
  void_int *elem_blk_ids       = NULL;
  void_int *ss_elem_ndx        = NULL;
  void_int *side_set_elem_list = NULL;
  void_int *side_set_side_list = NULL;
  size_t    elem_ctr;

  struct elem_blk_parm *elem_blk_parms = NULL;

  char errmsg[MAX_ERR_LENGTH];
  int  err_stat = EX_NOERR;

  ex_check_valid_file_id(exoid);

  exerrval = 0; /* clear error code */

  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */
  num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
  if (num_side_sets < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
             exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    return (EX_FATAL);
  }

  if (num_side_sets == 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no side sets defined in file id %d", exoid);
    ex_err("ex_get_side_set_node_count", errmsg, EX_WARN);
    return (EX_WARN);
  }

  /* Lookup index of side set id in VAR_SS_IDS array */
  ex_id_lkup(exoid, EX_SIDE_SET, side_set_id);
  if (exerrval != 0) {
    if (exerrval == EX_NULLENTITY) {
      snprintf(errmsg, MAX_ERR_LENGTH, "Warning: side set %" PRId64 " is NULL in file id %d",
               side_set_id, exoid);
      ex_err("ex_get_side_set_node_count", errmsg, EX_NULLENTITY);
      return (EX_WARN);
    }

    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to locate side set %" PRId64 " in VAR_SS_IDS array in file id %d",
             side_set_id, exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    return (EX_FATAL);
  }

  num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
  if (num_elem_blks < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of element blocks in file id %d",
             exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */
  ndim = ex_inquire_int(exoid, EX_INQ_DIM);
  if (ndim < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get dimensionality in file id %d", exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    return (EX_FATAL);
  }

  int int_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    int_size = sizeof(int64_t);
  }

  /* First determine the  # of elements in the side set*/
  int err;
  if (int_size == sizeof(int64_t)) {
    int64_t ss_elem = 0;
    int64_t ss_df   = 0;
    err             = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &ss_elem, &ss_df);
    tot_num_ss_elem = ss_elem;
  }
  else {
    int ss_elem     = 0;
    int ss_df       = 0;
    err             = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &ss_elem, &ss_df);
    tot_num_ss_elem = ss_elem;
  }

  if (err == -1) {
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to get number of elements in side set %" PRId64 " in file id %d",
             side_set_id, exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set element list */
  {
    if (!(side_set_elem_list = malloc(tot_num_ss_elem * int_size))) {
      exerrval = EX_MEMFAIL;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set element "
                                       "list for file id %d",
               exoid);
      ex_err("ex_get_side_set_node_count", errmsg, exerrval);
      return (EX_FATAL);
    }

    /* Allocate space for the side set side list */
    if (!(side_set_side_list = malloc(tot_num_ss_elem * int_size))) {
      free(side_set_elem_list);
      exerrval = EX_MEMFAIL;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set side list "
                                       "for file id %d",
               exoid);
      ex_err("ex_get_side_set_node_count", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    if (ex_get_set(exoid, EX_SIDE_SET, side_set_id, side_set_elem_list, side_set_side_list) == -1) {
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get side set %" PRId64 " in file id %d",
               side_set_id, exoid);
      ex_err("ex_get_side_set_node_count", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    /* Allocate space for the ss element index array */
    if (!(ss_elem_ndx = malloc(tot_num_ss_elem * int_size))) {
      exerrval = EX_MEMFAIL;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem sort "
                                       "array for file id %d",
               exoid);
      ex_err("ex_get_side_set_node_count", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    if (int_size == sizeof(int64_t)) {
      /* Sort side set element list into index array  - non-destructive */
      int64_t *elems = (int64_t *)ss_elem_ndx;
      for (i = 0; i < tot_num_ss_elem; i++) {
        elems[i] = i; /* init index array to current position */
      }
      ex_iqsort64(side_set_elem_list, elems, tot_num_ss_elem);
    }
    else {
      /* Sort side set element list into index array  - non-destructive */
      int *elems = (int *)ss_elem_ndx;
      for (i = 0; i < tot_num_ss_elem; i++) {
        elems[i] = i; /* init index array to current position */
      }
      ex_iqsort(side_set_elem_list, elems, tot_num_ss_elem);
    }
  }

  /* Allocate space for the element block ids */
  {
    int int_size = sizeof(int);
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      int_size = sizeof(int64_t);
    }

    if (!(elem_blk_ids = malloc(num_elem_blks * int_size))) {
      exerrval = EX_MEMFAIL;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for element block ids "
                                       "for file id %d",
               exoid);
      ex_err("ex_get_side_set_node_count", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids) == -1) {
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get element block ids in file id %d",
               exoid);
      ex_err("ex_get_side_set_node_count", errmsg, EX_MSG);
      err_stat = EX_FATAL;
      goto cleanup;
    }
  }

  /* Allocate space for the element block params */
  if (!(elem_blk_parms = malloc(num_elem_blks * sizeof(struct elem_blk_parm)))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for element block params "
                                     "for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_count", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  elem_ctr = 0;
  for (i = 0; i < num_elem_blks; i++) {
    ex_entity_id id;
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      id = ((int64_t *)elem_blk_ids)[i];
    }
    else {
      id = ((int *)elem_blk_ids)[i];
    }

    err_stat = ex_int_get_block_param(exoid, id, ndim, &elem_blk_parms[i]);
    if (err_stat != EX_NOERR) {
      goto cleanup;
    }

    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr; /* save elem number max */
  }

  /* Finally... Create the list of node counts for each face in the
   * side set.
   */

  j = 0; /* The current element block... */
  for (ii = 0; ii < tot_num_ss_elem; ii++) {

    if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
      i    = ((int64_t *)ss_elem_ndx)[ii];
      elem = ((int64_t *)side_set_elem_list)[i];
      side = ((int64_t *)side_set_side_list)[i] - 1; /* Convert to 0-based sides */
    }
    else {
      i    = ((int *)ss_elem_ndx)[ii];
      elem = ((int *)side_set_elem_list)[i];
      side = ((int *)side_set_side_list)[i] - 1; /* Convert to 0-based sides */
    }

    /*
     * Since the elements are being accessed in sorted, order, the
     * block that contains the elements must progress sequentially
     * from block 0 to block[num_elem_blks-1]. Once we find an element
     * not in this block, find a following block that contains it...
     */
    for (; j < num_elem_blks; j++) {
      if (elem <= elem_blk_parms[j].elem_ctr) {
        break;
      }
    }

    if (j < num_elem_blks) {
      assert(side < elem_blk_parms[j].num_sides);
      side_set_node_cnt_list[i] = elem_blk_parms[j].num_nodes_per_side[side];
    }
    else {
      exerrval = EX_BADPARAM;
      snprintf(errmsg, MAX_ERR_LENGTH,
               "ERROR: Invalid element number %" PRId64 " found in side set %" PRId64 " in file %d",
               elem, side_set_id, exoid);
      ex_err("ex_get_side_set_node_count", errmsg, EX_MSG);
      err_stat = EX_FATAL;
      goto cleanup;
    }
  }

/* All done: release connectivity array space, element block ids
 * array, element block parameters array, and side set element index
 * array
 */
cleanup:
  free(elem_blk_ids);
  free(elem_blk_parms);
  free(ss_elem_ndx);
  free(side_set_side_list);
  free(side_set_elem_list);

  return (err_stat);
}
Beispiel #5
0
int ex_get_side_set_node_list_len(int exoid,
                          int side_set_id,
                          int *side_set_node_list_len)
{
  int i, j, m;
  int  num_side_sets, num_elem_blks, num_df, ndim;
  int tot_num_elem = 0, tot_num_ss_elem = 0; 
  int *elem_blk_ids;
  int *ss_elem_ndx;
  int *side_set_elem_list, *side_set_side_list;
  int elem_ctr; 
  int num_elem_in_blk, num_nodes_per_elem, num_attr;
  float fdum;
  char *cdum, elem_type[MAX_STR_LENGTH+1];

  struct elem_blk_parm
  {
    char elem_type[MAX_STR_LENGTH+1];
    int elem_blk_id;
    int num_elem_in_blk;
    int num_nodes_per_elem;
    int num_nodes_per_side;
    int num_attr;
    int elem_ctr;
    int elem_type_val;
  } *elem_blk_parms;

  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  cdum = 0; /* initialize even though it is not used */

  *side_set_node_list_len = 0; /* default value */
/* first check if any side sets are specified */
/* inquire how many side sets have been stored */

  if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0)
  {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,EX_WARN);
    return(EX_WARN);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

/* get the dimensionality of the coordinates;  this is necessary to
   distinguish between 2d TRIs and 3d TRIs */

  if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* First determine the  # of elements in the side set*/
  if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1)
  {
    sprintf(errmsg,
         "Error: failed to get number of elements in side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (tot_num_ss_elem == 0) /* NULL side set? */
    return (EX_NOERR); /* return zero */

  /* Allocate space for the side set element list */
  if (!(side_set_elem_list=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set element list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set side list */
  if (!(side_set_side_list=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set side list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_side_set(exoid, side_set_id, 
                      side_set_elem_list, side_set_side_list) == -1)
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    sprintf(errmsg,
    "Error: failed to get side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
 "Error: failed to allocate space for side set elem sort array for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Sort side set element list into index array  - non-destructive */
  for (i=0;i<tot_num_ss_elem;i++)
    ss_elem_ndx[i] = i; /* init index array to current position */

  ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);


  /* Allocate space for the element block ids */
  if (!(elem_blk_ids=static_cast<int*>(malloc(num_elem_blks*sizeof(int)))))
  {
    exerrval = EX_MEMFAIL;
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
        "Error: failed to allocate space for element block ids for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_elem_blk_ids(exoid, elem_blk_ids))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
           "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms=static_cast<struct elem_blk_parm*>(malloc(num_elem_blks*sizeof(struct elem_blk_parm)))))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++)
  {
    /* read in an element block parameter */
    if ((ex_get_elem_block (exoid,
                            elem_blk_ids[i],
                            elem_type,
                            &num_elem_in_blk,
                            &num_nodes_per_elem,
                            &num_attr)) == -1)
    {
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      sprintf(errmsg,
             "Error: failed to get element block %d parameters in file id %d",
              elem_blk_ids[i], exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = num_elem_in_blk;
    elem_blk_parms[i].num_nodes_per_elem = num_nodes_per_elem;
    elem_blk_parms[i].num_attr = num_attr;
    elem_blk_parms[i].elem_blk_id = elem_blk_ids[i];

    for (m=0; m < strlen(elem_type); m++)
      elem_blk_parms[i].elem_type[m] = 
              toupper((int)elem_type[m]);
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = CIRCLE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SPHERE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = QUAD;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TRIANGLE;
      /* determine side set node stride */
      if (ndim == 2) /* 2d TRIs */
      {
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side = 2;
        else 
          elem_blk_parms[i].num_nodes_per_side = 3;
      }
      else if (ndim == 3)  /* 3d TRIs */
      {   /* set the default number of nodes per side; catch exceptions later */
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side = 3;
        else 
          elem_blk_parms[i].num_nodes_per_side = 6;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SHELL;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2) /* KLUDGE for 2D Shells*/
        elem_blk_parms[i].num_nodes_per_side = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = HEX;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 9)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 12) /* HEXSHELL */
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 27)
        elem_blk_parms[i].num_nodes_per_side = 9;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TETRA;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 3;
      else if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 6;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = WEDGE;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 6)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = PYRAMID;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = BEAM;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0)  ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0))
    {
      elem_blk_parms[i].elem_type_val = TRUSS;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = '\0';
      elem_blk_parms[i].num_nodes_per_side = 0;
      elem_blk_parms[i].num_elem_in_blk = 0;
    }
    else
    { /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = UNK;
      elem_blk_parms[i].num_nodes_per_side = 0;
    }

    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }

/* Walk through element list and keep a running count of the node length */

  *side_set_node_list_len = 0;
  for (i=0;i<tot_num_ss_elem;i++)
  {
    for (j=0; j<num_elem_blks; j++)
    {
      if (elem_blk_parms[j].elem_type_val != '\0')
        if (side_set_elem_list[i] <= elem_blk_parms[j].elem_ctr)
          break; /* stop because we found the parameters for this element */
    }
    if (j >= num_elem_blks)
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: Invalid element number %d found in side set %d in file %d",
              side_set_elem_list[i], side_set_id, exoid);
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return (EX_FATAL);
    }

    /* Update *side_set_node_list_len (which points to next node in chain */

    /* WEDGEs with 3 node sides (side 4 or 5) are special cases */
    if (elem_blk_parms[j].elem_type_val == WEDGE &&
        (side_set_side_list[i] == 4 || side_set_side_list[i] == 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 6)
        *side_set_node_list_len += 3;  /* 3 node side */
      else
        *side_set_node_list_len += 6;  /* 6 node side */
    }
    /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */
    else if (elem_blk_parms[j].elem_type_val == PYRAMID &&
             (side_set_side_list[i] < 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 5)
        *side_set_node_list_len += 3;  /* 3 node side */
      else
        *side_set_node_list_len += 6;  /* 6 node side */
    }
    /* side numbers 3,4,5,6 for SHELLs are also special */
    else if (elem_blk_parms[j].elem_type_val == SHELL &&
        (side_set_side_list[i] > 2 ))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 4)
        *side_set_node_list_len += 2;  /* 2 node side */
      else
        *side_set_node_list_len += 3;  /* 3 node side */
    }
    /* sides 3, 4, and 5 of 3d TRIs are special cases */
    else if (elem_blk_parms[j].elem_type_val == TRIANGLE &&
             ndim == 3 &&
             side_set_side_list[i] > 2 )
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 3)  /* 3-node TRI */
        *side_set_node_list_len += 2;  /* 2 node side */
      else  /* 6-node TRI */
        *side_set_node_list_len += 3;  /* 3 node side */
    }
    else if (elem_blk_parms[j].elem_type_val == UNK)
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: %s in elem block %d is an unsupported element type",
              elem_blk_parms[i].elem_type, elem_blk_parms[i].elem_blk_id);
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return (EX_FATAL);
    }
    else /* all other element types */
      *side_set_node_list_len += elem_blk_parms[j].num_nodes_per_side;
  }

  /* All done: release element block ids array,
     element block parameters array, and side set element index array */
  free(elem_blk_ids);
  free(elem_blk_parms);
  free(ss_elem_ndx);
  free(side_set_side_list);
  free(side_set_elem_list);

  return(EX_NOERR);
}
int ex_get_side_set_node_list(int exoid,
                              ex_entity_id side_set_id,
                              void_int *side_set_node_cnt_list,
                              void_int *side_set_node_list)
{
    size_t m;
    size_t i, j;
    int64_t elem, side;
    int64_t num_side_sets, num_elem_blks, num_df, ndim;
    int64_t tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0;
    size_t connect_offset, side_num, node_pos;
    void_int *elem_blk_ids = NULL;
    void_int *connect = NULL;
    void_int *ss_elem_ndx = NULL;
    void_int *ss_elem_node_ndx = NULL;
    void_int *ss_parm_ndx = NULL;
    void_int *side_set_elem_list = NULL;
    void_int *side_set_side_list = NULL;
    size_t elem_ctr, node_ctr, elem_num_pos;
    size_t num_nodes_per_elem;
    int int_size, ids_size;

    int err_stat = EX_NOERR;
    int status;

    struct elem_blk_parm  *elem_blk_parms = NULL;

    /* side to node translation tables -
       These tables are used to look up the side number based on the
       first and second node in the side/face list. The side node order
       is found in the original Exodus document, SAND87-2997. The element
       node order is found in the ExodusII document, SAND92-2137. These
       tables were generated by following the right-hand rule for determining
       the outward normal.
    */
    /* triangle */
    static int tri_table[3][3] = {
        /*   1        2        3                                             side   */
        {1,2,4}, {2,3,5}, {3,1,6}                                       /* nodes  */
    };

    /* triangle 3d */
    static int tri3_table[5][7] = {
        /*       1                2                                          side   */
        {1,2,3,4,5,6,7}, {3,2,1,6,5,4,7},                               /* nodes  */
        /*       3              4              5                             side   */
        {1,2,4,0,0,0,0}, {2,3,5,0,0,0,0}, {3,1,6,0,0,0,0}               /* nodes  */
    };

    /* quad */
    static int quad_table[4][3] = {
        /*   1        2        3        4                                    side   */
        {1,2,5}, {2,3,6}, {3,4,7}, {4,1,8}                              /* nodes  */
    };

    /* shell */
    static int shell_table[6][8] = {
        /*        1                  2                                       side   */
        {1,2,3,4,5,6,7,8}, {1,4,3,2,8,7,6,5} ,                          /* nodes  */
        /*        3                  4                                       side   */
        {1,2,5,0,0,0,0,0}, {2,3,6,0,0,0,0,0} ,                          /* nodes  */
        /*        5                  6                                       side   */
        {3,4,7,0,0,0,0,0}, {4,1,8,0,0,0,0,0}                            /* nodes  */
    };

    /* tetra */
    static int tetra_table[4][6] = {
        /*      1              2               3               4            side   */
        {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  */
    };

    /* wedge */
    static int wedge_table[5][8] = {
        /*        1                     2                     3              side   */
        {1,2,5,4,7,11,13,10}, {2,3,6,5,8,12,14,11}, {1,4,6,3,10,15,12,9},
        /*        4                  5                                       side   */
        {1,3,2,0,9,8,7,0}, {4,5,6,0,13,14,15,0}                         /* nodes  */
    };

    /* hex */
    static int hex_table[6][9] = {
        /*         1                        2                                side   */
        {1,2,6,5,9,14,17,13,26}, {2,3,7,6,10,15,18,14,25},              /* nodes  */
        /*         3                        4                                side   */
        {3,4,8,7,11,16,19,15,27}, {1,5,8,4,13,20,16,12,24},             /* nodes  */
        /*         5                        6                                side   */
        {1,4,3,2,12,11,10,9,22},  {5,6,7,8,17,18,19,20,23}              /* nodes  */
    };

    /* pyramid */
    static int pyramid_table[5][8] = {
        /*          1                   2                    3              side   */
        {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  */
        /*          4                  5                                    side   */
        {1,5,4,0,10,13,9,0}, {1,4,3,2,9,8,7,6}                         /* nodes  */
    };


    char errmsg[MAX_ERR_LENGTH];

    exerrval = 0; /* clear error code */

    /* first check if any side sets are specified */
    /* inquire how many side sets have been stored */

    num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
    if (num_side_sets < 0) {
        sprintf(errmsg,
                "Error: failed to get number of side sets in file id %d",exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return(EX_FATAL);
    }

    if (num_side_sets == 0) {
        sprintf(errmsg,
                "Warning: no side sets defined in file id %d",exoid);
        ex_err("ex_get_side_set_node_list",errmsg,EX_WARN);
        return(EX_WARN);
    }

    /* Lookup index of side set id in VAR_SS_IDS array */
    ex_id_lkup(exoid,EX_SIDE_SET,side_set_id);
    if (exerrval != 0)  {
        if (exerrval == EX_NULLENTITY) {
            sprintf(errmsg,
                    "Warning: side set %"PRId64" is NULL in file id %d",
                    side_set_id,exoid);
            ex_err("ex_get_side_set_node_list",errmsg,EX_NULLENTITY);
            return (EX_WARN);
        }
        else {

            sprintf(errmsg,
                    "Error: failed to locate side set %"PRId64" in VAR_SS_IDS array in file id %d",
                    side_set_id,exoid);
            ex_err("ex_get_side_set_node_list",errmsg,exerrval);
            return (EX_FATAL);
        }
    }

    num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
    if (num_elem_blks < 0) {
        sprintf(errmsg,
                "Error: failed to get number of element blocks in file id %d",exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return(EX_FATAL);
    }

    tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
    if (tot_num_elem < 0) {
        sprintf(errmsg,
                "Error: failed to get total number of elements in file id %d",exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return(EX_FATAL);
    }

    /* get the dimensionality of the coordinates;  this is necessary to
       distinguish between 2d TRIs and 3d TRIs */
    ndim = ex_inquire_int(exoid, EX_INQ_DIM);
    if (ndim < 0) {
        sprintf(errmsg,
                "Error: failed to get dimensionality in file id %d",exoid);
        ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
        return(EX_FATAL);
    }

    int_size = sizeof(int);
    if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
        int_size = sizeof(int64_t);
    }

    ids_size = sizeof(int);
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
        ids_size = sizeof(int64_t);
    }

    /* First determine the  # of elements in the side set*/
    if (int_size == sizeof(int64_t)) {
        status = ex_get_set_param(exoid,EX_SIDE_SET, side_set_id,&tot_num_ss_elem,&num_df);
    } else {
        int tot, df;
        status = ex_get_set_param(exoid,EX_SIDE_SET, side_set_id,&tot,&df);
        tot_num_ss_elem = tot;
        num_df = df;
    }

    if (status != EX_NOERR) {
        sprintf(errmsg,
                "Error: failed to get number of elements in side set %"PRId64" in file id %d",
                side_set_id, exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return(EX_FATAL);
    }

    /* Allocate space for the side set element list */
    if (!(side_set_elem_list=malloc(tot_num_ss_elem*int_size))) {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for side set element list for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return (EX_FATAL);
    }

    /* Allocate space for the side set side list */
    if (!(side_set_side_list=malloc(tot_num_ss_elem*int_size))) {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for side set side list for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
    }

    if (ex_get_set(exoid, EX_SIDE_SET, side_set_id,
                   side_set_elem_list, side_set_side_list) == -1) {
        safe_free(side_set_elem_list);
        safe_free(side_set_side_list);
        sprintf(errmsg,
                "Error: failed to get side set %"PRId64" in file id %d",
                side_set_id, exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return (EX_FATAL);
    }

    /* Allocate space for the ss element index array */
    if (!(ss_elem_ndx= malloc(tot_num_ss_elem*int_size))) {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for side set elem sort array for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
    }

    /* Sort side set element list into index array  - non-destructive */
    if (int_size == sizeof(int64_t)) {
        /* Sort side set element list into index array  - non-destructive */
        int64_t *elems = (int64_t*)ss_elem_ndx;
        for (i=0; i<tot_num_ss_elem; i++) {
            elems[i] = i; /* init index array to current position */
        }
        ex_iqsort64(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
    } else {
        /* Sort side set element list into index array  - non-destructive */
        int *elems = (int*)ss_elem_ndx;
        for (i=0; i<tot_num_ss_elem; i++) {
            elems[i] = i; /* init index array to current position */
        }
        ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
    }

    /* Allocate space for the element block ids */
    if (!(elem_blk_ids= malloc(num_elem_blks*ids_size))) {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for element block ids for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
    }

    if (ex_get_elem_blk_ids(exoid, elem_blk_ids) == -1) {
        sprintf(errmsg,
                "Error: failed to get element block ids in file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
        err_stat = EX_FATAL;
        goto cleanup;
    }

    /* Allocate space for the element block params */
    if (!(elem_blk_parms= malloc(num_elem_blks*sizeof(struct elem_blk_parm)))) {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for element block params for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
    }

    elem_ctr = 0;
    for (i=0; i<num_elem_blks; i++) {
        ex_block block;

        if (ids_size == sizeof(int64_t)) {
            block.id = ((int64_t*)elem_blk_ids)[i];
        } else {
            block.id = ((int*)elem_blk_ids)[i];
        }
        block.type = EX_ELEM_BLOCK;

        /* read in an element block parameter */
        if ((ex_get_block_param (exoid, &block)) == -1) {
            sprintf(errmsg,
                    "Error: failed to get element block %"PRId64" parameters in file id %d",
                    block.id, exoid);
            ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
            err_stat = EX_FATAL;
            goto cleanup;
        }

        elem_blk_parms[i].num_elem_in_blk = block.num_entry;
        elem_blk_parms[i].num_nodes_per_elem = block.num_nodes_per_entry;
        elem_blk_parms[i].num_attr = block.num_attribute;
        elem_blk_parms[i].elem_blk_id = block.id;

        for (m=0; m < strlen(block.topology); m++) {
            elem_blk_parms[i].elem_type[m] = toupper(block.topology[m]);
        }
        elem_blk_parms[i].elem_type[m] = '\0';

        if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_CIRCLE;
            /* set side set node stride */
            elem_blk_parms[i].num_nodes_per_side[0] = 1;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_SPHERE;
            /* set side set node stride */
            elem_blk_parms[i].num_nodes_per_side[0] = 1;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_QUAD;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 4)
                elem_blk_parms[i].num_nodes_per_side[0] = 2;
            else if (elem_blk_parms[i].num_nodes_per_elem == 5)
                elem_blk_parms[i].num_nodes_per_side[0] = 2;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 3;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_TRIANGLE;
            /* set default side set node stride */
            if (ndim == 2)  /* 2d TRIs */
            {
                if (elem_blk_parms[i].num_nodes_per_elem == 3)
                    elem_blk_parms[i].num_nodes_per_side[0] = 2;
                else
                    elem_blk_parms[i].num_nodes_per_side[0] = 3;
            }
            else if (ndim == 3)  /* 3d TRIs */
            {
                if (elem_blk_parms[i].num_nodes_per_elem == 3)
                    elem_blk_parms[i].num_nodes_per_side[0] = 3;
                else
                    elem_blk_parms[i].num_nodes_per_side[0] = 6;
            }
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_SHELL;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 2) /* KLUDGE for 2D Shells*/
                elem_blk_parms[i].num_nodes_per_side[0] = 2;
            else if (elem_blk_parms[i].num_nodes_per_elem == 4)
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 8;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_HEX;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 8)  /* 8-node bricks */
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else if (elem_blk_parms[i].num_nodes_per_elem == 9)  /* 9-node bricks */
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else if (elem_blk_parms[i].num_nodes_per_elem == 12)  /* HEXSHELLS */
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else if (elem_blk_parms[i].num_nodes_per_elem == 27)  /* 27-node bricks */
                elem_blk_parms[i].num_nodes_per_side[0] = 9;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 8;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_TETRA;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 4)
                elem_blk_parms[i].num_nodes_per_side[0] = 3;
            else if (elem_blk_parms[i].num_nodes_per_elem == 8)
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 6;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_WEDGE;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 6)
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 8;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_PYRAMID;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 5)
                elem_blk_parms[i].num_nodes_per_side[0] = 4;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 8;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_BEAM;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 2)
                elem_blk_parms[i].num_nodes_per_side[0] = 2;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 3;
        }
        else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
                  (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0) ||
                  (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
        {
            elem_blk_parms[i].elem_type_val = EX_EL_TRUSS;
            /* determine side set node stride */
            if (elem_blk_parms[i].num_nodes_per_elem == 2)
                elem_blk_parms[i].num_nodes_per_side[0] = 2;
            else
                elem_blk_parms[i].num_nodes_per_side[0] = 3;
        }
        else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
        {
            elem_blk_parms[i].elem_type_val = EX_EL_NULL_ELEMENT;
            elem_blk_parms[i].num_nodes_per_side[0] = 0;
            elem_blk_parms[i].num_elem_in_blk = 0;
        }
        else
        {   /* unsupported element type; no problem if no sides specified for
            this element block */
            elem_blk_parms[i].elem_type_val = EX_EL_UNK;
            elem_blk_parms[i].num_nodes_per_side[0] = 0;
        }
        elem_blk_parms[i].elem_blk_id = block.id;    /* save id */
        elem_ctr += elem_blk_parms[i].num_elem_in_blk;
        elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
    }


    /* Allocate space for the ss element to element block parameter index array */
    if (!(ss_parm_ndx=malloc(tot_num_ss_elem*int_size)))
    {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for side set elem parms index for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
    }


    /* Allocate space for the ss element to node list index array */
    if (!(ss_elem_node_ndx=malloc(tot_num_ss_elem*int_size)))
    {
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
                "Error: failed to allocate space for side set elem to node index for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);

        err_stat = EX_FATAL;
        goto cleanup;
    }

    /* Build side set element to node list index and side set element
       parameter index.
    */
    node_ctr = 0;
    for (i=0; i<tot_num_ss_elem; i++) {
        if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
            elem = ((int64_t*)side_set_elem_list)[i];
            side = ((int64_t*)side_set_side_list)[i];
        } else {
            elem = ((int*)side_set_elem_list)[i];
            side = ((int*)side_set_side_list)[i];
        }

        for (j=0; j<num_elem_blks; j++) {
            if (elem_blk_parms[j].elem_type_val != EX_EL_NULL_ELEMENT)
                if (elem <= elem_blk_parms[j].elem_ctr)
                    break;
        }

        if (j >= num_elem_blks) {
            exerrval = EX_BADPARAM;
            sprintf(errmsg,
                    "Error: Invalid element number %"PRId64" found in side set %"PRId64" in file %d",
                    elem, side_set_id, exoid);
            ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
            err_stat = EX_FATAL;
            goto cleanup;
        }

        if (int_size == sizeof(int64_t)) {
            ((int64_t*)ss_parm_ndx)[i] = j; /* assign parameter block index */
            ((int64_t*)ss_elem_node_ndx)[i] = node_ctr;     /* assign node list index */
        } else {
            ((int*)ss_parm_ndx)[i] = j; /* assign parameter block index */
            ((int*)ss_elem_node_ndx)[i] = node_ctr;     /* assign node list index */
        }

        /* Update node_ctr (which points to next node in chain */

        /* WEDGEs with 3 node sides (side 4 or 5) are special cases */
        if (elem_blk_parms[j].elem_type_val == EX_EL_WEDGE &&
                (side == 4 || side == 5))
        {
            if (elem_blk_parms[j].num_nodes_per_elem == 6)
                node_ctr += 3;  /* 3 node side */
            else
                node_ctr += 6;  /* 6 node side */
        }
        /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */
        else if (elem_blk_parms[j].elem_type_val == EX_EL_PYRAMID &&
                 (side < 5))
        {
            if (elem_blk_parms[j].num_nodes_per_elem == 5)
                node_ctr += 3;  /* 3 node side */
            else
                node_ctr += 6;  /* 6 node side */
        }
        /* side numbers 3,4,5,6 for SHELLs are also special */
        else if (elem_blk_parms[j].elem_type_val == EX_EL_SHELL &&
                 (side > 2 ))
        {
            if (elem_blk_parms[j].num_nodes_per_elem == 4)
                node_ctr += 2;  /* 2 node side */
            else
                node_ctr += 3;  /* 3 node side */
        }
        /* side numbers 3,4,5 for 3d TRIs are also special */
        else if (elem_blk_parms[j].elem_type_val == EX_EL_TRIANGLE &&
                 ndim == 3 &&
                 side > 2 )
        {
            if (elem_blk_parms[j].num_nodes_per_elem == 3)  /* 3-node TRI */
                node_ctr += 2;  /* 2 node side */
            else   /* 6-node TRI */
                node_ctr += 3;  /* 3 node side */
        }
        else /* all other element types */
            node_ctr += elem_blk_parms[j].num_nodes_per_side[0];
    }

    /* All setup, ready to go ... */

    elem_ctr=0;

    for (j=0; j < tot_num_ss_elem; j++) {
        int64_t elem_ndx;
        size_t parm_ndx;
        if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
            elem_ndx = ((int64_t*)ss_elem_ndx)[j];
            elem     = ((int64_t*)side_set_elem_list)[elem_ndx];
            side     = ((int64_t*)side_set_side_list)[elem_ndx];
            parm_ndx = ((int64_t*)ss_parm_ndx)[elem_ndx];
        } else {
            elem_ndx = ((int*)ss_elem_ndx)[j];
            elem     = ((int*)side_set_elem_list)[elem_ndx];
            side     = ((int*)side_set_side_list)[elem_ndx];
            parm_ndx = ((int*)ss_parm_ndx)[elem_ndx];
        }

        if (elem > elem_ctr) {
            /* release connectivity array space and get next one */
            if (elem_ctr > 0) {
                safe_free(connect);
            }

            /* Allocate space for the connectivity array for new element block */
            if (!(connect=malloc(elem_blk_parms[parm_ndx].num_elem_in_blk*
                                 elem_blk_parms[parm_ndx].num_nodes_per_elem*
                                 int_size)))
            {
                exerrval = EX_MEMFAIL;
                sprintf(errmsg,
                        "Error: failed to allocate space for connectivity array for file id %d",
                        exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            /* get connectivity array */
            if (ex_get_elem_conn(exoid,
                                 elem_blk_parms[parm_ndx].elem_blk_id,
                                 connect) == -1)
            {
                sprintf(errmsg,
                        "Error: failed to allocate space for connectivity array for file id %d",
                        exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }
            elem_ctr = elem_blk_parms[parm_ndx].elem_ctr;
        }
        /*  For each side in side set, use the appropriate lookup table to
        determine the nodes from the connect array. */

        elem_num = elem-1;/* element number 0-based*/
        /* calculate the relative element number position in it's block*/

        elem_num_pos = elem_num -
                       (elem_blk_parms[parm_ndx].elem_ctr -
                        elem_blk_parms[parm_ndx].num_elem_in_blk);

        /* calculate the beginning of the node list for this element by
           using the ss_elem_node_ndx index into the side_sets_node_index
           and adding the element number position * number of nodes per elem */

        num_nodes_per_elem = elem_blk_parms[parm_ndx].num_nodes_per_elem;
        connect_offset = num_nodes_per_elem*elem_num_pos;
        side_num = side-1;

        if (int_size == sizeof(int64_t)) {
            node_pos = ((int64_t*)ss_elem_node_ndx)[elem_ndx];
        } else {
            node_pos = ((int*)ss_elem_node_ndx)[elem_ndx];
        }

        switch (elem_blk_parms[parm_ndx].elem_type_val)
        {
        case EX_EL_CIRCLE:
        case EX_EL_SPHERE:
        {   /* Note: no side-node lookup table is used for this simple case */
            get_nodes(exoid, side_set_node_list, node_pos, connect, connect_offset);
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 1);   /* 1 node object */
            break;
        }
        case EX_EL_TRUSS:
        case EX_EL_BEAM:
        {   /* Note: no side-node lookup table is used for this simple case */
            for (i=0; i < num_nodes_per_elem; i++) {
                get_nodes(exoid, side_set_node_list, node_pos+i, connect, connect_offset+i);
            }
            set_count(exoid, side_set_node_cnt_list, elem_ndx, num_nodes_per_elem);
            break;
        }
        case EX_EL_TRIANGLE:
        {
            if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid triangle edge number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            if (ndim == 2)   /* 2d TRIs */
            {
                get_nodes(exoid, side_set_node_list, node_pos,   connect, connect_offset+tri_table[side_num][0]-1);
                get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+tri_table[side_num][1]-1);
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 2);   /* 2 node object */
                if (num_nodes_per_elem > 3)   /* 6-node TRI  */
                {
                    get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+tri_table[side_num][2]-1);
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
                }
            }
            else if (ndim == 3)  /* 3d TRIs */
            {
                get_nodes(exoid, side_set_node_list, node_pos,   connect, connect_offset+tri3_table[side_num][0]-1);
                get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+tri3_table[side_num][1]-1);
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 2);   /* 2 node object */
                if (side_num+1 <= 2)  /* 3- or 6-node face */
                {
                    if (num_nodes_per_elem == 3)  /* 3-node face */
                    {
                        set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
                        get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+tri3_table[side_num][2]-1);
                    }
                    else   /* 6-node face */
                    {
                        set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node object */
                        get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+tri3_table[side_num][2]-1);
                        get_nodes(exoid, side_set_node_list, node_pos+3, connect, connect_offset+tri3_table[side_num][3]-1);
                        get_nodes(exoid, side_set_node_list, node_pos+4, connect, connect_offset+tri3_table[side_num][4]-1);
                        get_nodes(exoid, side_set_node_list, node_pos+5, connect, connect_offset+tri3_table[side_num][5]-1);
                    }
                }
                else /* 2- or 3-node edge */
                {
                    if (num_nodes_per_elem > 3)  /* 3-node edge */
                    {
                        set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
                        get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+tri3_table[side_num][2]-1);
                    }
                }
            }
            break;
        }
        case EX_EL_QUAD:
        {
            if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid quad edge number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos+0, connect, connect_offset+quad_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+quad_table[side_num][1]-1);
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 2);   /* 2 node object */
            if (num_nodes_per_elem > 5)
            {
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
                get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+quad_table[side_num][2]-1);
            }
            break;
        }
        case EX_EL_SHELL:
        {
            if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid shell face number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos+0, connect, connect_offset+shell_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+shell_table[side_num][1]-1);
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 2);   /* 2 node object */
            if (num_nodes_per_elem > 2) /*** KLUDGE for 2D shells ***/
            {
                if (side_num+1 <= 2)  /* 4-node face */
                {
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 4);   /* 4 node object */
                    get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+shell_table[side_num][2]-1);
                    get_nodes(exoid, side_set_node_list, node_pos+3, connect, connect_offset+shell_table[side_num][3]-1);
                }
            }
            if (num_nodes_per_elem == 8)
            {
                if (side_num+1 <= 2)  /* 8-node face */
                {
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 8); /* 8 node object */
                    get_nodes(exoid, side_set_node_list, node_pos+4, connect, connect_offset+shell_table[side_num][4]-1);
                    get_nodes(exoid, side_set_node_list, node_pos+5, connect, connect_offset+shell_table[side_num][5]-1);
                    get_nodes(exoid, side_set_node_list, node_pos+6, connect, connect_offset+shell_table[side_num][6]-1);
                    get_nodes(exoid, side_set_node_list, node_pos+7, connect, connect_offset+shell_table[side_num][7]-1);
                }
                else
                {
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node edge */
                    get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+shell_table[side_num][2]-1);
                }
            }
            break;
        }
        case EX_EL_TETRA:
        {
            if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid tetra face number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos+0, connect, connect_offset+tetra_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+tetra_table[side_num][1]-1);
            get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+tetra_table[side_num][2]-1);
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 3);   /* 3 node object */
            if (num_nodes_per_elem == 8)
            {
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node object */
                get_nodes(exoid, side_set_node_list, node_pos+3, connect, connect_offset+tetra_table[side_num][3]-1);
            }
            else if (num_nodes_per_elem > 8)
            {
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node object */
                get_nodes(exoid, side_set_node_list, node_pos+3, connect, connect_offset+tetra_table[side_num][3]-1);
                get_nodes(exoid, side_set_node_list, node_pos+4, connect, connect_offset+tetra_table[side_num][4]-1);
                get_nodes(exoid, side_set_node_list, node_pos+5, connect, connect_offset+tetra_table[side_num][5]-1);
            }
            break;
        }
        case EX_EL_WEDGE:
        {
            if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid wedge face number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][1]-1);
            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][2]-1);

            if (wedge_table[side_num][3] == 0) { /* degenerate side? */
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 3);   /* 3 node side */
            }
            else
            {
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][3]-1);
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 4);   /* 4 node side */
            }


            if (num_nodes_per_elem > 6)
            {
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][4]-1);
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][5]-1);
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][6]-1);

                if (wedge_table[side_num][7] == 0) /* degenerate side? */
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 7);   /* 6 node side */
                else
                {
                    get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+wedge_table[side_num][7]-1);
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 8);   /* 8 node side */
                }
            }
            break;
        }
        case EX_EL_PYRAMID:
        {
            if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid pyramid face number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][1]-1);
            get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][2]-1);

            if (pyramid_table[side_num][3] == 0) { /* degenerate side? */
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 3);   /* 3 node side */
            }
            else
            {
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][3]-1);
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 4);   /* 4 node side */
            }


            if (num_nodes_per_elem > 5)
            {
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][4]-1);
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][5]-1);
                get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][6]-1);

                if (pyramid_table[side_num][7] == 0) /* degenerate side? */
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 7);   /* 6 node side */
                else
                {
                    get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset+pyramid_table[side_num][7]-1);
                    set_count(exoid, side_set_node_cnt_list, elem_ndx, 8);   /* 8 node side */
                }
            }
            break;
        }
        case EX_EL_HEX:
        {
            if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
            {
                exerrval = EX_BADPARAM;
                sprintf(errmsg,
                        "Error: Invalid hex face number %"ST_ZU" in file id %d",
                        side_num+1, exoid);
                ex_err("ex_get_side_set_node_list",errmsg,exerrval);
                err_stat = EX_FATAL;
                goto cleanup;
            }

            get_nodes(exoid, side_set_node_list, node_pos+0, connect, connect_offset+hex_table[side_num][0]-1);
            get_nodes(exoid, side_set_node_list, node_pos+1, connect, connect_offset+hex_table[side_num][1]-1);
            get_nodes(exoid, side_set_node_list, node_pos+2, connect, connect_offset+hex_table[side_num][2]-1);
            get_nodes(exoid, side_set_node_list, node_pos+3, connect, connect_offset+hex_table[side_num][3]-1);
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 4);   /* 4 node object */
            if (num_nodes_per_elem > 12)   /* more nodes than HEXSHELL */
            {
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 8); /* 8 node object */
                get_nodes(exoid, side_set_node_list, node_pos+4, connect, connect_offset+hex_table[side_num][4]-1);
                get_nodes(exoid, side_set_node_list, node_pos+5, connect, connect_offset+hex_table[side_num][5]-1);
                get_nodes(exoid, side_set_node_list, node_pos+6, connect, connect_offset+hex_table[side_num][6]-1);
                get_nodes(exoid, side_set_node_list, node_pos+7, connect, connect_offset+hex_table[side_num][7]-1);
            }
            if (num_nodes_per_elem == 27)                 /* 27-node brick */
            {
                set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node object */
                get_nodes(exoid, side_set_node_list, node_pos+8, connect, connect_offset+hex_table[side_num][8]-1);
            }
            break;
        }
        default:
        {
            exerrval = EX_BADPARAM;
            sprintf(errmsg,
                    "Error: %s is an unsupported element type",
                    elem_blk_parms[parm_ndx].elem_type);
            ex_err("ex_get_side_set_node_list",errmsg,exerrval);
            return(EX_FATAL);
        }
        }
    }


    /* All done: release connectivity array space, element block ids array,
       element block parameters array, and side set element index array */
cleanup:
    safe_free(connect);
    safe_free(ss_parm_ndx);
    safe_free(elem_blk_ids);
    safe_free(elem_blk_parms);
    safe_free(ss_elem_ndx);
    safe_free(ss_elem_node_ndx);
    safe_free(side_set_side_list);
    safe_free(side_set_elem_list);

    return(err_stat);
}
int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *side_set_node_cnt_list,
                              void_int *side_set_node_list)
{
  size_t    i, j;
  int64_t   elem, side;
  int64_t   num_side_sets, num_elem_blks, num_df, ndim;
  int64_t   tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0;
  size_t    connect_offset, side_num, node_pos;
  void_int *elem_blk_ids       = NULL;
  void_int *connect            = NULL;
  void_int *ss_elem_ndx        = NULL;
  void_int *ss_elem_node_ndx   = NULL;
  void_int *ss_parm_ndx        = NULL;
  void_int *side_set_elem_list = NULL;
  void_int *side_set_side_list = NULL;
  size_t    elem_ctr, node_ctr, elem_num_pos;
  size_t    num_nodes_per_elem;
  int       int_size, ids_size;

  int err_stat = EX_NOERR;
  int status;

  struct elem_blk_parm *elem_blk_parms = NULL;

  /* side to node translation tables -
     These tables are used to look up the side number based on the
     first and second node in the side/face list. The side node order
     is found in the original Exodus document, SAND87-2997. The element
     node order is found in the ExodusII document, SAND92-2137. These
     tables were generated by following the right-hand rule for determining
     the outward normal.
  */
  /* triangle */
  static int tri_table[3][3] = {
      {1, 2, 4}, /* side 1 */
      {2, 3, 5}, /* side 2 */
      {3, 1, 6}  /* side 3 */
  };

  /* triangle 3d */
  static int tri3_table[5][7] = {
      {1, 2, 3, 4, 5, 6, 7}, /* side 1 (face) */
      {3, 2, 1, 6, 5, 4, 7}, /* side 2 (face) */
      {1, 2, 4, 0, 0, 0, 0}, /* side 3 (edge) */
      {2, 3, 5, 0, 0, 0, 0}, /* side 4 (edge) */
      {3, 1, 6, 0, 0, 0, 0}  /* side 5 (edge) */
  };

  /* quad */
  static int quad_table[4][3] = {
      {1, 2, 5}, /* side 1 */
      {2, 3, 6}, /* side 2 */
      {3, 4, 7}, /* side 3 */
      {4, 1, 8}  /* side 4 */
  };

  /* shell */
  static int shell_table[6][9] = {
      {1, 2, 3, 4, 5, 6, 7, 8, 9}, /* side 1 (face) */
      {1, 4, 3, 2, 8, 7, 6, 5, 9}, /* side 2 (face) */
      {1, 2, 5, 0, 0, 0, 0, 0, 0}, /* side 3 (edge) */
      {2, 3, 6, 0, 0, 0, 0, 0, 0}, /* side 4 (edge) */
      {3, 4, 7, 0, 0, 0, 0, 0, 0}, /* side 5 (edge) */
      {4, 1, 8, 0, 0, 0, 0, 0, 0}  /* side 6 (edge) */
  };

  /* tetra */
  static int tetra_table[4][7] = {
      {1, 2, 4, 5, 9, 8, 14},  /* Side 1 nodes */
      {2, 3, 4, 6, 10, 9, 12}, /* Side 2 nodes */
      {1, 4, 3, 8, 10, 7, 13}, /* Side 3 nodes */
      {1, 3, 2, 7, 6, 5, 11}   /* Side 4 nodes */
  };

  /* wedge */
  /* wedge 6 or 7 */
  static int wedge6_table[5][4] = {
      {1, 2, 5, 4}, /* Side 1 nodes -- quad     */
      {2, 3, 6, 5}, /* Side 2 nodes -- quad     */
      {1, 4, 6, 3}, /* Side 3 nodes -- quad     */
      {1, 3, 2, 0}, /* Side 4 nodes -- triangle */
      {4, 5, 6, 0}  /* Side 5 nodes -- triangle */
  };

  /* wedge 15 or 16 */
  static int wedge15_table[5][8] = {
      {1, 2, 5, 4, 7, 11, 13, 10}, /* Side 1 nodes -- quad     */
      {2, 3, 6, 5, 8, 12, 14, 11}, /* Side 2 nodes -- quad     */
      {1, 4, 6, 3, 10, 15, 12, 9}, /* Side 3 nodes -- quad     */
      {1, 3, 2, 9, 8, 7, 0, 0},    /* Side 4 nodes -- triangle */
      {4, 5, 6, 13, 14, 15, 0, 0}  /* Side 5 nodes -- triangle */
  };

  /* wedge 20 */
  static int wedge20_table[5][9] = {
      {1, 2, 5, 4, 7, 11, 13, 10, 20}, /* Side 1 nodes -- quad     */
      {2, 3, 6, 5, 8, 12, 14, 11, 18}, /* Side 2 nodes -- quad     */
      {1, 4, 6, 3, 10, 15, 12, 9, 19}, /* Side 3 nodes -- quad     */
      {1, 3, 2, 9, 8, 7, 16, 0, 0},    /* Side 4 nodes -- triangle */
      {4, 5, 6, 13, 14, 15, 17, 0, 0}  /* Side 5 nodes -- triangle */
  };

  /* wedge 21 */
  static int wedge21_table[5][9] = {
      {1, 2, 5, 4, 7, 11, 13, 10, 21}, /* Side 1 nodes -- quad     */
      {2, 3, 6, 5, 8, 12, 14, 11, 19}, /* Side 2 nodes -- quad     */
      {1, 4, 6, 3, 10, 15, 12, 9, 20}, /* Side 3 nodes -- quad     */
      {1, 3, 2, 9, 8, 7, 17, 0, 0},    /* Side 4 nodes -- triangle */
      {4, 5, 6, 13, 14, 15, 18, 0, 0}  /* Side 5 nodes -- triangle */
  };

  /* wedge 18 */
  static int wedge18_table[5][9] = {
      {1, 2, 5, 4, 7, 11, 13, 10, 16}, /* Side 1 nodes -- quad     */
      {2, 3, 6, 5, 8, 12, 14, 11, 17}, /* Side 2 nodes -- quad     */
      {1, 4, 6, 3, 10, 15, 12, 9, 18}, /* Side 3 nodes -- quad     */
      {1, 3, 2, 9, 8, 7, 0, 0, 0},     /* Side 4 nodes -- triangle */
      {4, 5, 6, 13, 14, 15, 0, 0, 0}   /* Side 5 nodes -- triangle */
  };

  /* hex */
  static int hex_table[6][9] = {
      {1, 2, 6, 5, 9, 14, 17, 13, 26},  /* side 1 */
      {2, 3, 7, 6, 10, 15, 18, 14, 25}, /* side 2 */
      {3, 4, 8, 7, 11, 16, 19, 15, 27}, /* side 3 */
      {1, 5, 8, 4, 13, 20, 16, 12, 24}, /* side 4 */
      {1, 4, 3, 2, 12, 11, 10, 9, 22},  /* side 5 */
      {5, 6, 7, 8, 17, 18, 19, 20, 23}  /* side 6 */
  };

  /* pyramid */
  static int pyramid_table[5][9] = {
      {1, 2, 5, 0, 6, 11, 10, 0, 15}, /* side 1 (tri) */
      {2, 3, 5, 0, 7, 12, 11, 0, 16}, /* side 2 (tri) */
      {3, 4, 5, 0, 8, 13, 12, 0, 17}, /* side 3 (tri) */
      {1, 5, 4, 0, 10, 13, 9, 0, 18}, /* side 4 (tri) */
      {1, 4, 3, 2, 9, 8, 7, 6, 14}    /* side 5 (quad) */
  };

  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */
  num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
  if (num_side_sets < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  if (num_side_sets == 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no side sets defined in file id %d", exoid);
    ex_err("ex_get_side_set_node_list", errmsg, EX_WARN);
    return (EX_WARN);
  }

  /* Lookup index of side set id in VAR_SS_IDS array */
  ex_id_lkup(exoid, EX_SIDE_SET, side_set_id);
  if (exerrval != 0) {
    if (exerrval == EX_NULLENTITY) {
      snprintf(errmsg, MAX_ERR_LENGTH, "Warning: side set %" PRId64 " is NULL in file id %d",
               side_set_id, exoid);
      ex_err("ex_get_side_set_node_list", errmsg, EX_NULLENTITY);
      return (EX_WARN);
    }

    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to locate side set %" PRId64 " in VAR_SS_IDS array in file id %d",
             side_set_id, exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
  if (num_elem_blks < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of element blocks in file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
  if (tot_num_elem < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get total number of elements in file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */
  ndim = ex_inquire_int(exoid, EX_INQ_DIM);
  if (ndim < 0) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get dimensionality in file id %d", exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  int_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    int_size = sizeof(int64_t);
  }

  ids_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
    ids_size = sizeof(int64_t);
  }

  /* First determine the  # of elements in the side set*/
  if (int_size == sizeof(int64_t)) {
    status = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &tot_num_ss_elem, &num_df);
  }
  else {
    int tot, df;
    status          = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &tot, &df);
    tot_num_ss_elem = tot;
    num_df          = df;
  }

  if (status != EX_NOERR) {
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to get number of elements in side set %" PRId64 " in file id %d",
             side_set_id, exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set element list */
  if (!(side_set_elem_list = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set element list "
                                     "for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set side list */
  if (!(side_set_side_list = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to allocate space for side set side list for file id %d", exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  if (ex_get_set(exoid, EX_SIDE_SET, side_set_id, side_set_elem_list, side_set_side_list) == -1) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get side set %" PRId64 " in file id %d",
             side_set_id, exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem sort "
                                     "array for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Sort side set element list into index array  - non-destructive */
  if (int_size == sizeof(int64_t)) {
    /* Sort side set element list into index array  - non-destructive */
    int64_t *elems = (int64_t *)ss_elem_ndx;
    for (i = 0; i < tot_num_ss_elem; i++) {
      elems[i] = i; /* init index array to current position */
    }
    ex_iqsort64(side_set_elem_list, ss_elem_ndx, tot_num_ss_elem);
  }
  else {
    /* Sort side set element list into index array  - non-destructive */
    int *elems = (int *)ss_elem_ndx;
    for (i = 0; i < tot_num_ss_elem; i++) {
      elems[i] = i; /* init index array to current position */
    }
    ex_iqsort(side_set_elem_list, ss_elem_ndx, tot_num_ss_elem);
  }

  /* Allocate space for the element block ids */
  if (!(elem_blk_ids = malloc(num_elem_blks * ids_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: failed to allocate space for element block ids for file id %d", exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids) == -1) {
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get element block ids in file id %d", exoid);
    ex_err("ex_get_side_set_node_list", errmsg, EX_MSG);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Allocate space for the element block params */
  if (!(elem_blk_parms = malloc(num_elem_blks * sizeof(struct elem_blk_parm)))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for element block params "
                                     "for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  elem_ctr = 0;
  for (i = 0; i < num_elem_blks; i++) {
    ex_entity_id id;
    if (ids_size == sizeof(int64_t)) {
      id = ((int64_t *)elem_blk_ids)[i];
    }
    else {
      id = ((int *)elem_blk_ids)[i];
    }

    err_stat = ex_int_get_block_param(exoid, id, ndim, &elem_blk_parms[i]);
    if (err_stat != EX_NOERR) {
      goto cleanup;
    }

    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr; /* save elem number max */
  }

  /* Allocate space for the ss element to element block parameter index array */
  if (!(ss_parm_ndx = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem parms "
                                     "index for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);
    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Allocate space for the ss element to node list index array */
  if (!(ss_elem_node_ndx = malloc(tot_num_ss_elem * int_size))) {
    exerrval = EX_MEMFAIL;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for side set elem to node "
                                     "index for file id %d",
             exoid);
    ex_err("ex_get_side_set_node_list", errmsg, exerrval);

    err_stat = EX_FATAL;
    goto cleanup;
  }

  /* Build side set element to node list index and side set element
     parameter index.
  */
  node_ctr = 0;
  for (i = 0; i < tot_num_ss_elem; i++) {
    if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
      elem = ((int64_t *)side_set_elem_list)[i];
      side = ((int64_t *)side_set_side_list)[i];
    }
    else {
      elem = ((int *)side_set_elem_list)[i];
      side = ((int *)side_set_side_list)[i];
    }

    for (j = 0; j < num_elem_blks; j++) {
      if (elem_blk_parms[j].elem_type_val != EX_EL_NULL_ELEMENT) {
        if (elem <= elem_blk_parms[j].elem_ctr) {
          break;
        }
      }
    }

    if (j >= num_elem_blks) {
      exerrval = EX_BADPARAM;
      snprintf(errmsg, MAX_ERR_LENGTH,
               "ERROR: Invalid element number %" PRId64 " found in side set %" PRId64 " in file %d",
               elem, side_set_id, exoid);
      ex_err("ex_get_side_set_node_list", errmsg, EX_MSG);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    if (int_size == sizeof(int64_t)) {
      ((int64_t *)ss_parm_ndx)[i]      = j;        /* assign parameter block index */
      ((int64_t *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */
    }
    else {
      ((int *)ss_parm_ndx)[i]      = j;        /* assign parameter block index */
      ((int *)ss_elem_node_ndx)[i] = node_ctr; /* assign node list index */
    }

    /* Update node_ctr (which points to next node in chain */
    node_ctr += elem_blk_parms[j].num_nodes_per_side[side - 1];
  }

  /* All setup, ready to go ... */

  elem_ctr = 0;

  for (j = 0; j < tot_num_ss_elem; j++) {
    int64_t elem_ndx;
    size_t  parm_ndx;
    if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
      elem_ndx = ((int64_t *)ss_elem_ndx)[j];
      elem     = ((int64_t *)side_set_elem_list)[elem_ndx];
      side     = ((int64_t *)side_set_side_list)[elem_ndx];
      parm_ndx = ((int64_t *)ss_parm_ndx)[elem_ndx];
    }
    else {
      elem_ndx = ((int *)ss_elem_ndx)[j];
      elem     = ((int *)side_set_elem_list)[elem_ndx];
      side     = ((int *)side_set_side_list)[elem_ndx];
      parm_ndx = ((int *)ss_parm_ndx)[elem_ndx];
    }

    if (elem > elem_ctr) {
      /* release connectivity array space and get next one */
      if (elem_ctr > 0) {
        free(connect);
      }

      /* Allocate space for the connectivity array for new element block */
      if (!(connect = malloc(elem_blk_parms[parm_ndx].num_elem_in_blk *
                             elem_blk_parms[parm_ndx].num_nodes_per_elem * int_size))) {
        exerrval = EX_MEMFAIL;
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for connectivity "
                                         "array for file id %d",
                 exoid);
        ex_err("ex_get_side_set_node_list", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }

      /* get connectivity array */
      if (ex_get_conn(exoid, EX_ELEM_BLOCK, elem_blk_parms[parm_ndx].elem_blk_id, connect, NULL,
                      NULL) == -1) {
        snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to allocate space for connectivity "
                                         "array for file id %d",
                 exoid);
        ex_err("ex_get_side_set_node_list", errmsg, exerrval);
        err_stat = EX_FATAL;
        goto cleanup;
      }
      elem_ctr = elem_blk_parms[parm_ndx].elem_ctr;
    }

    if (connect == NULL) {
      snprintf(errmsg, MAX_ERR_LENGTH,
               "ERROR: internal error -- connect pointer is NULL for file id %d", exoid);
      ex_err("ex_get_side_set_node_list", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }

    /*  For each side in side set, use the appropriate lookup table to
        determine the nodes from the connect array. */

    elem_num = elem - 1; /* element number 0-based*/
    /* calculate the relative element number position in it's block*/

    elem_num_pos =
        elem_num - (elem_blk_parms[parm_ndx].elem_ctr - elem_blk_parms[parm_ndx].num_elem_in_blk);

    /* calculate the beginning of the node list for this element by
       using the ss_elem_node_ndx index into the side_sets_node_index
       and adding the element number position * number of nodes per elem */

    num_nodes_per_elem = elem_blk_parms[parm_ndx].num_nodes_per_elem;
    connect_offset     = num_nodes_per_elem * elem_num_pos;
    side_num           = side - 1;

    if (int_size == sizeof(int64_t)) {
      node_pos = ((int64_t *)ss_elem_node_ndx)[elem_ndx];
    }
    else {
      node_pos = ((int *)ss_elem_node_ndx)[elem_ndx];
    }

    switch (elem_blk_parms[parm_ndx].elem_type_val) {
    case EX_EL_CIRCLE:
    case EX_EL_SPHERE: { /* Note: no side-node lookup table is used for this
                            simple case */
      get_nodes(exoid, side_set_node_list, node_pos, connect, connect_offset);
      set_count(exoid, side_set_node_cnt_list, elem_ndx, 1); /* 1 node object */
      break;
    }
    case EX_EL_TRUSS:
    case EX_EL_BEAM: { /* Note: no side-node lookup table is used for this
                          simple case */
      for (i = 0; i < num_nodes_per_elem; i++) {
        get_nodes(exoid, side_set_node_list, node_pos + i, connect, connect_offset + i);
      }
      set_count(exoid, side_set_node_cnt_list, elem_ndx, num_nodes_per_elem);
      break;
    }
    case EX_EL_TRIANGLE: {
      if (ndim == 2) { /* 2d TRIs */
        if (check_valid_side(side_num, 3, "triangle", exoid) != EX_NOERR) {
          goto cleanup;
        }

        get_nodes(exoid, side_set_node_list, node_pos, connect,
                  connect_offset + tri_table[side_num][0] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                  connect_offset + tri_table[side_num][1] - 1);
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 2); /* 2 node object */
        if (num_nodes_per_elem > 3)                            /* 6-node TRI  */
        {
          get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                    connect_offset + tri_table[side_num][2] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
        }
      }
      else if (ndim == 3) { /* 3d TRIs */
        if (check_valid_side(side_num, 5, "triangle", exoid) != EX_NOERR) {
          goto cleanup;
        }

        get_nodes(exoid, side_set_node_list, node_pos, connect,
                  connect_offset + tri3_table[side_num][0] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                  connect_offset + tri3_table[side_num][1] - 1);
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 2); /* 2 node object */
        if (side_num + 1 <= 2)                                 /* 3, 4, 6, 7-node face */
        {
          if (num_nodes_per_elem == 3) /* 3-node face */
          {
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + tri3_table[side_num][2] - 1);
          }
          else if (num_nodes_per_elem == 4) /* 4-node face */
          {
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node object */
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + tri3_table[side_num][2] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + 4 - 1); /* Center node of 4-noded face */
          }
          else if (num_nodes_per_elem == 6) /* 6-node face */
          {
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node object */
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + tri3_table[side_num][2] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                      connect_offset + tri3_table[side_num][3] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                      connect_offset + tri3_table[side_num][4] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                      connect_offset + tri3_table[side_num][5] - 1);
          }
          else if (num_nodes_per_elem == 7) /* 7-node face */
          {
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 7); /* 7 node object */
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + tri3_table[side_num][2] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                      connect_offset + tri3_table[side_num][3] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                      connect_offset + tri3_table[side_num][4] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                      connect_offset + tri3_table[side_num][5] - 1);
            get_nodes(exoid, side_set_node_list, node_pos + 6, connect,
                      connect_offset + tri3_table[side_num][6] - 1);
          }
          else {
            snprintf(errmsg, MAX_ERR_LENGTH,
                     "ERROR: %d is an unsupported number of nodes for the triangle element type",
                     (int)num_nodes_per_elem);
            ex_err("ex_get_side_set_node_list", errmsg, exerrval);
            err_stat = EX_FATAL;
            goto cleanup;
          }
        }
        else /* 2- or 3-node edge */
        {
          if (num_nodes_per_elem > 3) /* 3-node edge */
          {
            set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
            get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                      connect_offset + tri3_table[side_num][2] - 1);
          }
        }
      }
      break;
    }
    case EX_EL_QUAD: {
      if (check_valid_side(side_num, 4, "quad", exoid) != EX_NOERR) {
        goto cleanup;
      }

      get_nodes(exoid, side_set_node_list, node_pos + 0, connect,
                connect_offset + quad_table[side_num][0] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                connect_offset + quad_table[side_num][1] - 1);
      set_count(exoid, side_set_node_cnt_list, elem_ndx, 2); /* 2 node object */
      if (num_nodes_per_elem > 5) {
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
        get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                  connect_offset + quad_table[side_num][2] - 1);
      }
      break;
    }
    case EX_EL_SHELL: {
      if (check_valid_side(side_num, 6, "shell", exoid) != EX_NOERR) {
        goto cleanup;
      }

      get_nodes(exoid, side_set_node_list, node_pos + 0, connect,
                connect_offset + shell_table[side_num][0] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                connect_offset + shell_table[side_num][1] - 1);
      set_count(exoid, side_set_node_cnt_list, elem_ndx, 2);     /* 2 node object */
      if (num_nodes_per_elem > 2) {                              /*** KLUGE for 2D shells ***/
        if (side_num + 1 <= 2) {                                 /* 4-node face */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node object */
          get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                    connect_offset + shell_table[side_num][2] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                    connect_offset + shell_table[side_num][3] - 1);
        }
      }
      if (num_nodes_per_elem == 8) {
        if (side_num + 1 <= 2) {                                 /* 8-node face */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 8); /* 8 node object */
          get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                    connect_offset + shell_table[side_num][4] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                    connect_offset + shell_table[side_num][5] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 6, connect,
                    connect_offset + shell_table[side_num][6] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 7, connect,
                    connect_offset + shell_table[side_num][7] - 1);
        }
        else {
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node edge */
          get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                    connect_offset + shell_table[side_num][2] - 1);
        }
      }
      if (num_nodes_per_elem == 9) {
        if (side_num + 1 <= 2) {                                 /* 9-node face */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node object */
          get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                    connect_offset + shell_table[side_num][4] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                    connect_offset + shell_table[side_num][5] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 6, connect,
                    connect_offset + shell_table[side_num][6] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 7, connect,
                    connect_offset + shell_table[side_num][7] - 1);
          get_nodes(exoid, side_set_node_list, node_pos + 8, connect,
                    connect_offset + shell_table[side_num][8] - 1);
        }
        else {
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node edge */
          get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                    connect_offset + shell_table[side_num][2] - 1);
        }
      }
      break;
    }
    case EX_EL_TETRA: {
      if (check_valid_side(side_num, 4, "tetra", exoid) != EX_NOERR) {
        goto cleanup;
      }

      get_nodes(exoid, side_set_node_list, node_pos + 0, connect,
                connect_offset + tetra_table[side_num][0] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                connect_offset + tetra_table[side_num][1] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                connect_offset + tetra_table[side_num][2] - 1);
      set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node object */
      if (num_nodes_per_elem == 8) {
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node object */
        get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                  connect_offset + tetra_table[side_num][3] - 1);
      }
      else if (num_nodes_per_elem > 8) {
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node object */
        get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                  connect_offset + tetra_table[side_num][3] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                  connect_offset + tetra_table[side_num][4] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                  connect_offset + tetra_table[side_num][5] - 1);
      }
      break;
    }
    case EX_EL_WEDGE: {
      int node_off = 0;
      if (check_valid_side(side_num, 5, "wedge", exoid) != EX_NOERR) {
        goto cleanup;
      }

      if (num_nodes_per_elem == 6 || num_nodes_per_elem == 7) {
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge6_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge6_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge6_table[side_num][node_off++] - 1);

        if (side_num == 3 || side_num == 4) {
          /* This is one of the triangular faces */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node side */
          assert(node_off == 3);
        }
        else {
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge6_table[side_num][node_off++] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node side */
          assert(node_off == 4);
        }
      }

      else if (num_nodes_per_elem == 15 || num_nodes_per_elem == 16) {
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge15_table[side_num][node_off++] - 1);

        if (side_num == 3 || side_num == 4) {
          /* This is one of the triangular faces */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node side */
          assert(node_off == 6);
        }
        else {
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge15_table[side_num][node_off++] - 1);
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge15_table[side_num][node_off++] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 8); /* 8 node side */
          assert(node_off == 8);
        }
      }
      else if (num_nodes_per_elem == 20) {
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge20_table[side_num][node_off++] - 1);

        if (side_num == 3 || side_num == 4) {
          /* This is one of the triangular faces */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 7); /* 7 node side */
          assert(node_off == 7);
        }
        else {
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge20_table[side_num][node_off++] - 1);
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge20_table[side_num][node_off++] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node side */
          assert(node_off == 9);
        }
      }
      else if (num_nodes_per_elem == 21) {
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge21_table[side_num][node_off++] - 1);

        if (side_num == 3 || side_num == 4) {
          /* This is one of the triangular faces */
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 7); /* 7 node side */
        }
        else {
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge21_table[side_num][node_off++] - 1);
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge21_table[side_num][node_off++] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node side */
        }
      }
      else if (num_nodes_per_elem == 18) {
        /* Wedge 18 - 9-node quad faces (0,1,2) and 6-node tri faces (3,4) */
        /* All faces (quad or tri) have at least 6 nodes */
        /* This gets nodes 1-6 */
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + wedge18_table[side_num][node_off++] - 1);

        if (side_num == 3 || side_num == 4) {
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 6); /* 6 node side */
          assert(node_off == 6);
        }
        else {
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge18_table[side_num][node_off++] - 1);
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge18_table[side_num][node_off++] - 1);
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + wedge18_table[side_num][node_off++] - 1);
          set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node side */
          assert(node_off == 9);
        }
      }
      break;
    }
    case EX_EL_PYRAMID: {
      /*
       * node count:  5 -- 4-node quad, 3-node tri
       *             13    8            6
       *             14    9            6
       *             18    9            7
       *             19    9            7  + volume center node.
       */

      if (check_valid_side(side_num, 5, "pyramid", exoid) != EX_NOERR) {
        goto cleanup;
      }

      get_nodes(exoid, side_set_node_list, node_pos++, connect,
                connect_offset + pyramid_table[side_num][0] - 1);
      get_nodes(exoid, side_set_node_list, node_pos++, connect,
                connect_offset + pyramid_table[side_num][1] - 1);
      get_nodes(exoid, side_set_node_list, node_pos++, connect,
                connect_offset + pyramid_table[side_num][2] - 1);

      if (pyramid_table[side_num][3] == 0) {                   /* degenerate side? */
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 3); /* 3 node side */
      }
      else {
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + pyramid_table[side_num][3] - 1);
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node side */
      }

      if (num_nodes_per_elem > 5) {
        /* This gets the mid-edge nodes for three edges */
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + pyramid_table[side_num][4] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + pyramid_table[side_num][5] - 1);
        get_nodes(exoid, side_set_node_list, node_pos++, connect,
                  connect_offset + pyramid_table[side_num][6] - 1);

        if (side_num == 4) {
          int face_node_count = num_nodes_per_elem >= 14 ? 9 : 8;
          set_count(exoid, side_set_node_cnt_list, elem_ndx, face_node_count);

          /* Get the last mid-edge node if this is quad face topology */
          get_nodes(exoid, side_set_node_list, node_pos++, connect,
                    connect_offset + pyramid_table[side_num][7] - 1);

          if (num_nodes_per_elem >= 14) {
            /* Get the mid-face node for the quad */
            get_nodes(exoid, side_set_node_list, node_pos++, connect,
                      connect_offset + pyramid_table[side_num][8] - 1);
          }
        }
        else {
          /* Triangular faces... */
          int face_node_count = num_nodes_per_elem >= 18 ? 7 : 6;
          set_count(exoid, side_set_node_cnt_list, elem_ndx, face_node_count);

          if (num_nodes_per_elem >= 18) {
            /* Get the mid-face node for the tri */
            get_nodes(exoid, side_set_node_list, node_pos++, connect,
                      connect_offset + pyramid_table[side_num][8] - 1);
          }
        }
      }
      break;
    }
    case EX_EL_HEX: {
      if (check_valid_side(side_num, 6, "hex", exoid) != EX_NOERR) {
        goto cleanup;
      }

      get_nodes(exoid, side_set_node_list, node_pos + 0, connect,
                connect_offset + hex_table[side_num][0] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 1, connect,
                connect_offset + hex_table[side_num][1] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 2, connect,
                connect_offset + hex_table[side_num][2] - 1);
      get_nodes(exoid, side_set_node_list, node_pos + 3, connect,
                connect_offset + hex_table[side_num][3] - 1);
      set_count(exoid, side_set_node_cnt_list, elem_ndx, 4); /* 4 node object */
      if (num_nodes_per_elem > 12)                           /* more nodes than HEXSHELL */
      {
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 8); /* 8 node object */
        get_nodes(exoid, side_set_node_list, node_pos + 4, connect,
                  connect_offset + hex_table[side_num][4] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 5, connect,
                  connect_offset + hex_table[side_num][5] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 6, connect,
                  connect_offset + hex_table[side_num][6] - 1);
        get_nodes(exoid, side_set_node_list, node_pos + 7, connect,
                  connect_offset + hex_table[side_num][7] - 1);
      }
      if (num_nodes_per_elem == 27) /* 27-node brick */
      {
        set_count(exoid, side_set_node_cnt_list, elem_ndx, 9); /* 9 node object */
        get_nodes(exoid, side_set_node_list, node_pos + 8, connect,
                  connect_offset + hex_table[side_num][8] - 1);
      }
      break;
    }
    default: {
      exerrval = EX_BADPARAM;
      snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: %s is an unsupported element type",
               elem_blk_parms[parm_ndx].elem_type);
      ex_err("ex_get_side_set_node_list", errmsg, exerrval);
      err_stat = EX_FATAL;
      goto cleanup;
    }
    }
  }

/* All done: release connectivity array space, element block ids array,
   element block parameters array, and side set element index array */
cleanup:
  free(connect);
  free(ss_parm_ndx);
  free(elem_blk_ids);
  free(elem_blk_parms);
  free(ss_elem_ndx);
  free(ss_elem_node_ndx);
  free(side_set_side_list);
  free(side_set_elem_list);

  return (err_stat);
}
int ex_get_side_set_node_list_len(int exoid,
				  ex_entity_id side_set_id,
				  void_int *side_set_node_list_len)
{
  size_t i, j;
  size_t m;
  int64_t num_side_sets, num_elem_blks, num_df, ndim;
  size_t list_len = 0;
  int64_t tot_num_elem = 0, tot_num_ss_elem = 0; 
  void_int *elem_blk_ids;
  int *ss_elem_ndx = NULL;
  int64_t *ss_elem_ndx_64 = NULL;
  
  void_int *side_set_elem_list;
  void_int *side_set_side_list;
  int elem_ctr; 
  int status;
  
  struct elem_blk_parm  *elem_blk_parms;

  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

    if (ex_int64_status(exoid) & EX_BULK_INT64_API)
      *(int64_t*)side_set_node_list_len = 0; /* default value */
    else
      *(int*)side_set_node_list_len = 0; /* default value */
      
  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */

  ndim = ex_inquire_int(exoid, EX_INQ_DIM);
  if (ndim < 0)  {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
  if (tot_num_elem < 0) {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
  if (num_elem_blks < 0) {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
  if (num_side_sets < 0) {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0) {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,EX_WARN);
    return(EX_WARN);
  }

  /* First determine the  # of elements in the side set*/
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    status = ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df);
  } else {
    int tot;
    int df;
    status = ex_get_side_set_param(exoid,side_set_id,&tot,&df);
    tot_num_ss_elem = tot;
    num_df = df;
  }

  if (status != NC_NOERR) {
    sprintf(errmsg,
         "Error: failed to get number of elements in side set %"PRId64" in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (tot_num_ss_elem == 0) /* NULL side set? */
    return (EX_NOERR); /* return zero */

  /* Minor optimization/kluge -- If num_df is nonzero, or 1 per face
     then assume that it matches the number of nodes in the sideset... */
  if (num_df > 0 && num_df != tot_num_ss_elem) {
    if (ex_int64_status(exoid) & EX_BULK_INT64_API)
      *(int64_t*)side_set_node_list_len = num_df;
    else
      *(int*)side_set_node_list_len = num_df;
    return(EX_NOERR);
  }

  /* Allocate space for the side set element list */
  {
    int int_size = sizeof(int);
    if (ex_int64_status(exoid) & EX_BULK_INT64_API)
      int_size = sizeof(int64_t);
    if (!(side_set_elem_list=malloc(tot_num_ss_elem*int_size))) {
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set element list for file id %d",
	      exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
      return (EX_FATAL);
    }

    /* Allocate space for the side set side list */
    if (!(side_set_side_list=malloc(tot_num_ss_elem*int_size))) {
      safe_free(side_set_elem_list);
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set side list for file id %d",
	      exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
      return (EX_FATAL);
    }

    if (ex_get_side_set(exoid, side_set_id, 
			side_set_elem_list, side_set_side_list) != NC_NOERR) {
      safe_free(side_set_elem_list);
      safe_free(side_set_side_list);
      sprintf(errmsg,
	      "Error: failed to get side set %"PRId64" in file id %d",
	      side_set_id, exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
      return (EX_FATAL);
    }
    
    /* Allocate space for the ss element index array */
    if (int_size == sizeof(int64_t)) {
      ss_elem_ndx_64=malloc(tot_num_ss_elem*int_size);
    } else {
      ss_elem_ndx   =malloc(tot_num_ss_elem*int_size);
    }

    if (ss_elem_ndx_64==NULL && ss_elem_ndx == NULL) {
      safe_free(side_set_elem_list);
      safe_free(side_set_side_list);
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set elem sort array for file id %d",
	      exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
      return (EX_FATAL);
    }
  }

  /* Sort side set element list into index array  - non-destructive */
  if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
    for (i=0;i<tot_num_ss_elem;i++)
      ss_elem_ndx_64[i] = i; /* init index array to current position */
    ex_iqsort64(side_set_elem_list, ss_elem_ndx_64,tot_num_ss_elem);
  } else {
    for (i=0;i<tot_num_ss_elem;i++)
      ss_elem_ndx[i] = i; /* init index array to current position */
    ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
  }


  /* Allocate space for the element block ids */
  {
    int int_size = sizeof(int);
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      int_size = sizeof(int64_t);
    }

    if (!(elem_blk_ids=malloc(num_elem_blks*int_size))) {
      exerrval = EX_MEMFAIL;
      safe_free(ss_elem_ndx);
      safe_free(ss_elem_ndx_64);
      safe_free(side_set_side_list);
      safe_free(side_set_elem_list);
      sprintf(errmsg,
	      "Error: failed to allocate space for element block ids for file id %d",
	      exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
      return (EX_FATAL);
    }
  }
  
  if (ex_get_elem_blk_ids(exoid, elem_blk_ids)) {
    safe_free(elem_blk_ids);
    safe_free(ss_elem_ndx);
    safe_free(ss_elem_ndx_64);
    safe_free(side_set_side_list);
    safe_free(side_set_elem_list);
    sprintf(errmsg,
	    "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms=malloc(num_elem_blks*sizeof(struct elem_blk_parm)))) {
    safe_free(elem_blk_ids);
    safe_free(ss_elem_ndx);
    safe_free(ss_elem_ndx_64);
    safe_free(side_set_side_list);
    safe_free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list_len",errmsg,exerrval);
    return (EX_FATAL);
  }

  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++) {
    ex_block block;
    block.type = EX_ELEM_BLOCK;
    
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      block.id = ((int64_t*)elem_blk_ids)[i];
    } else {
      block.id = ((int*)elem_blk_ids)[i];
    }

    /* read in an element block parameter */
    if ((ex_get_block_param (exoid, &block)) != NC_NOERR) {
      safe_free(elem_blk_parms);
      safe_free(elem_blk_ids);
      safe_free(ss_elem_ndx);
      safe_free(ss_elem_ndx_64);
      safe_free(side_set_side_list);
      safe_free(side_set_elem_list);
      sprintf(errmsg,
             "Error: failed to get element block %"PRId64" parameters in file id %d",
              block.id, exoid);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = block.num_entry;
    elem_blk_parms[i].num_nodes_per_elem = block.num_nodes_per_entry;
    elem_blk_parms[i].num_attr = block.num_attribute;
    elem_blk_parms[i].elem_blk_id = block.id;

    for (m=0; m < strlen(block.topology); m++) {
      elem_blk_parms[i].elem_type[m] = toupper(block.topology[m]);
    }
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_CIRCLE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_SPHERE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_QUAD;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TRIANGLE;
      /* determine side set node stride */
      if (ndim == 2) /* 2d TRIs */
      {
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side[0] = 2;
        else 
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
      }
      else if (ndim == 3)  /* 3d TRIs */
      {   /* set the default number of nodes per side; catch exceptions later */
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
        else 
          elem_blk_parms[i].num_nodes_per_side[0] = 6;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_SHELL;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2) /* KLUDGE for 2D Shells*/
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_HEX;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 9)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 12) /* HEXSHELL */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 27)
        elem_blk_parms[i].num_nodes_per_side[0] = 9;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TETRA;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
      else if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_WEDGE;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 6)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_PYRAMID;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
      else
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_BEAM;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0)  ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0))
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TRUSS;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_NULL_ELEMENT;
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
      elem_blk_parms[i].num_elem_in_blk = 0;
    }
    else
    { /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = EX_EL_UNK;
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
    }

    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }

/* Walk through element list and keep a running count of the node length */

  list_len = 0;
  for (i=0;i<tot_num_ss_elem;i++)
  {
    size_t elem;
    size_t side;
    if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
      elem = ((int64_t*)side_set_elem_list)[i];
      side = ((int64_t*)side_set_side_list)[i];
    } else {
      elem = ((int*)side_set_elem_list)[i];
      side = ((int*)side_set_side_list)[i];
    }

    for (j=0; j<num_elem_blks; j++)
    {
      if (elem_blk_parms[j].elem_type_val != EX_EL_NULL_ELEMENT)
        if (elem <= elem_blk_parms[j].elem_ctr)
          break; /* stop because we found the parameters for this element */
    }
    if (j >= num_elem_blks)
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: Invalid element number %"ST_ZU" found in side set %"PRId64" in file %d",
              elem, side_set_id, exoid);
      safe_free(elem_blk_parms);
      safe_free(elem_blk_ids);
      safe_free(ss_elem_ndx);
      safe_free(ss_elem_ndx_64);
      safe_free(side_set_side_list);
      safe_free(side_set_elem_list);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return (EX_FATAL);
    }

    /* Update *side_set_node_list_len (which points to next node in chain */

    /* WEDGEs with 3 node sides (side 4 or 5) are special cases */
    if (elem_blk_parms[j].elem_type_val == EX_EL_WEDGE &&
        (side == 4 || side == 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 6)
        list_len += 3;  /* 3 node side */
      else
        list_len += 6;  /* 6 node side */
    }
    /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */
    else if (elem_blk_parms[j].elem_type_val == EX_EL_PYRAMID &&
             (side < 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 5)
        list_len += 3;  /* 3 node side */
      else
        list_len += 6;  /* 6 node side */
    }
    /* side numbers 3,4,5,6 for SHELLs are also special */
    else if (elem_blk_parms[j].elem_type_val == EX_EL_SHELL &&
        (side > 2 ))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 4)
        list_len += 2;  /* 2 node side */
      else
        list_len += 3;  /* 3 node side */
    }
    /* sides 3, 4, and 5 of 3d TRIs are special cases */
    else if (elem_blk_parms[j].elem_type_val == EX_EL_TRIANGLE &&
             ndim == 3 && side > 2 )
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 3)  /* 3-node TRI */
        list_len += 2;  /* 2 node side */
      else  /* 6-node TRI */
        list_len += 3;  /* 3 node side */
    }
    else if (elem_blk_parms[j].elem_type_val == EX_EL_UNK)
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: %s in elem block %"PRId64" is an unsupported element type",
              elem_blk_parms[i].elem_type, elem_blk_parms[i].elem_blk_id);
      safe_free(elem_blk_parms);
      safe_free(elem_blk_ids);
      safe_free(ss_elem_ndx);
      safe_free(ss_elem_ndx_64);
      safe_free(side_set_side_list);
      safe_free(side_set_elem_list);
      ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG);
      return (EX_FATAL);
    }
    else /* all other element types */
      list_len += elem_blk_parms[j].num_nodes_per_side[0];
  }

  if (ex_int64_status(exoid) & EX_BULK_INT64_API)
    *(int64_t*)side_set_node_list_len = list_len;
  else
    *(int*)side_set_node_list_len = list_len;

  /* All done: release element block ids array,
     element block parameters array, and side set element index array */
  safe_free(elem_blk_ids);
  safe_free(elem_blk_parms);
  safe_free(ss_elem_ndx);
  safe_free(ss_elem_ndx_64);
  safe_free(side_set_side_list);
  safe_free(side_set_elem_list);

  return(EX_NOERR);
}
Beispiel #9
0
int ex_get_side_set_node_list(int exoid,
                          int side_set_id,
                          int *side_set_node_cnt_list,
                          int *side_set_node_list)
{
  int i, j, m; 
  int  num_side_sets, num_elem_blks, num_df, ndim;
  int tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0;
  int connect_offset, side_num, node_pos;
  int *elem_blk_ids, *connect; 
  int *ss_elem_ndx, *ss_elem_node_ndx, *ss_parm_ndx;
  int *side_set_elem_list, *side_set_side_list;
  int elem_ctr, node_ctr, elem_num_pos;
  int num_elem_in_blk, num_nodes_per_elem, num_attr;
  float fdum;
  char *cdum, elem_type[MAX_STR_LENGTH+1];

  struct elem_blk_parm
  {
    char elem_type[MAX_STR_LENGTH+1];
    int elem_blk_id;
    int num_elem_in_blk;
    int num_nodes_per_elem;
    int num_nodes_per_side;
    int num_attr;
    int elem_ctr;
    int elem_type_val;
  } *elem_blk_parms;

/* side to node translation tables - 
     These tables are used to look up the side number based on the
     first and second node in the side/face list. The side node order
     is found in the original Exodus document, SAND87-2997. The element
     node order is found in the ExodusII document, SAND92-2137. These
     tables were generated by following the right-hand rule for determining
     the outward normal.
*/
  /* triangle */
  static int tri_table[3][3] = {
  /*   1        2        3                                             side   */
    {1,2,4}, {2,3,5}, {3,1,6}                                       /* nodes  */
  };

  /* triangle 3d */
  static int tri3_table[5][7] = {
  /*       1                2                                          side   */
    {1,2,3,4,5,6,7}, {3,2,1,6,5,4,7},                               /* nodes  */
  /*       3              4              5                             side   */
    {1,2,4,0,0,0,0}, {2,3,5,0,0,0,0}, {3,1,6,0,0,0,0}               /* nodes  */
  };

  /* quad */
  static int quad_table[4][3] = {
  /*   1        2        3        4                                    side   */
    {1,2,5}, {2,3,6}, {3,4,7}, {4,1,8}                              /* nodes  */
  };

  /* shell */
  static int shell_table[6][8] = {
  /*        1                  2                                       side   */
    {1,2,3,4,5,6,7,8}, {1,4,3,2,8,7,6,5} ,                          /* nodes  */
  /*        3                  4                                       side   */
    {1,2,5,0,0,0,0,0}, {2,3,6,0,0,0,0,0} ,                          /* nodes  */
  /*        5                  6                                       side   */
    {3,4,7,0,0,0,0,0}, {4,1,8,0,0,0,0,0}                            /* nodes  */
  };

  /* tetra */
  static int tetra_table[4][6] = {
  /*      1              2               3               4            side   */
    {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  */
  };

  /* wedge */
  static int wedge_table[5][8] = {
  /*        1                     2                     3              side   */
    {1,2,5,4,7,11,13,10}, {2,3,6,5,8,12,14,11}, {1,4,6,3,10,15,12,9},
  /*        4                  5                                       side   */
    {1,3,2,0,9,8,7,0}, {4,5,6,0,13,14,15,0}                         /* nodes  */
  };

  /* hex */
  static int hex_table[6][9] = {
  /*         1                        2                                side   */
    {1,2,6,5,9,14,17,13,26}, {2,3,7,6,10,15,18,14,25},              /* nodes  */
  /*         3                        4                                side   */
    {3,4,8,7,11,16,19,15,27}, {1,5,8,4,13,20,16,12,24},             /* nodes  */
  /*         5                        6                                side   */
    {1,4,3,2,12,11,10,9,22},  {5,6,7,8,17,18,19,20,23}              /* nodes  */
  };

  /* pyramid */
  static int pyramid_table[5][8] = {
  /*          1                   2                    3              side   */
    {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  */
  /*          4                  5                                    side   */
    {1,5,4,0,10,13,9,0}, {1,4,3,2,9,8,7,6}                         /* nodes  */
  };


  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  cdum = 0; /* initialize even though it is not used */

/* first check if any side sets are specified */
/* inquire how many side sets have been stored */

  if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0)
  {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_get_side_set_node_list",errmsg,EX_WARN);
    return(EX_WARN);
  }

/* Lookup index of side set id in VAR_SS_IDS array */

  ex_id_lkup(exoid,VAR_SS_IDS,side_set_id);
  if (exerrval != 0) 
  {
     if (exerrval == EX_NULLENTITY)
     {
       sprintf(errmsg,
              "Warning: side set %d is NULL in file id %d",
               side_set_id,exoid);
       ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
       return (EX_WARN);
     }
     else
     {

     sprintf(errmsg,
     "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d",
             side_set_id,exoid);
     ex_err("ex_get_side_set_node_list",errmsg,exerrval);
     return (EX_FATAL);
     }
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return(EX_FATAL);
  }

  if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return(EX_FATAL);
  }

/* get the dimensionality of the coordinates;  this is necessary to
   distinguish between 2d TRIs and 3d TRIs */

  if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1)
  {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* First determine the  # of elements in the side set*/
  if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1)
  {
    sprintf(errmsg,
         "Error: failed to get number of elements in side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* Allocate space for the side set element list */
  if (!(side_set_elem_list=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set element list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the side set side list */
  if (!(side_set_side_list=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
    "Error: failed to allocate space for side set side list for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_side_set(exoid, side_set_id, 
                      side_set_elem_list, side_set_side_list) == -1)
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    sprintf(errmsg,
    "Error: failed to get side set %d in file id %d",
            side_set_id, exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Allocate space for the ss element index array */
  if (!(ss_elem_ndx= static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(side_set_elem_list);
    free(side_set_side_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
 "Error: failed to allocate space for side set elem sort array for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  /* Sort side set element list into index array  - non-destructive */
  for (i=0;i<tot_num_ss_elem;i++)
    ss_elem_ndx[i] = i; /* init index array to current position */

  ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);


  /* Allocate space for the element block ids */
  if (!(elem_blk_ids= static_cast<int*>(malloc(num_elem_blks*sizeof(int)))))
  {
    exerrval = EX_MEMFAIL;
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
        "Error: failed to allocate space for element block ids for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  if (ex_get_elem_blk_ids(exoid, elem_blk_ids) == -1)
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    sprintf(errmsg,
           "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms= static_cast<struct elem_blk_parm*>(malloc(num_elem_blks*sizeof(struct elem_blk_parm)))))
  {
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }

  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++)
  {
    /* read in an element block parameter */
    if ((ex_get_elem_block (exoid,
                            elem_blk_ids[i],
                            elem_type,
                            &num_elem_in_blk,
                            &num_nodes_per_elem,
                            &num_attr)) == -1)
    {
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      sprintf(errmsg,
             "Error: failed to get element block %d parameters in file id %d",
              elem_blk_ids[i], exoid);
      ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = num_elem_in_blk;
    elem_blk_parms[i].num_nodes_per_elem = num_nodes_per_elem;
    elem_blk_parms[i].num_attr = num_attr;

    for (m=0; m < strlen(elem_type); m++)
      elem_blk_parms[i].elem_type[m] = 
              toupper((int)elem_type[m]);
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = CIRCLE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SPHERE;
      /* set side set node stride */
        elem_blk_parms[i].num_nodes_per_side = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = QUAD;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TRIANGLE;
      /* set default side set node stride */
      if (ndim == 2)  /* 2d TRIs */
      {
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side = 2;
        else 
          elem_blk_parms[i].num_nodes_per_side = 3;
      }
      else if (ndim == 3)  /* 3d TRIs */
      {
        if (elem_blk_parms[i].num_nodes_per_elem == 3)
          elem_blk_parms[i].num_nodes_per_side = 3;
        else 
          elem_blk_parms[i].num_nodes_per_side = 6;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = SHELL;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2) /* KLUDGE for 2D Shells*/
        elem_blk_parms[i].num_nodes_per_side = 2;
      else if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = HEX;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8)  /* 8-node bricks */
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 9)  /* 9-node bricks */
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 12)  /* HEXSHELLS */
        elem_blk_parms[i].num_nodes_per_side = 4;
      else if (elem_blk_parms[i].num_nodes_per_elem == 27)  /* 27-node bricks */
        elem_blk_parms[i].num_nodes_per_side = 9;
      else 
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = TETRA;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4)
        elem_blk_parms[i].num_nodes_per_side = 3;
      else if (elem_blk_parms[i].num_nodes_per_elem == 8)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 6;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = WEDGE;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 6)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = PYRAMID;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 5)
        elem_blk_parms[i].num_nodes_per_side = 4;
      else
        elem_blk_parms[i].num_nodes_per_side = 8;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = BEAM;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
    {
      elem_blk_parms[i].elem_type_val = TRUSS;
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 2)
        elem_blk_parms[i].num_nodes_per_side = 2;
      else 
        elem_blk_parms[i].num_nodes_per_side = 3;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = '\0';
      elem_blk_parms[i].num_nodes_per_side = 0;
      elem_blk_parms[i].num_elem_in_blk = 0;
    }
    else
    { /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = UNK;
      elem_blk_parms[i].num_nodes_per_side = 0;
    }
    elem_blk_parms[i].elem_blk_id = elem_blk_ids[i];    /* save id */
    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }


  /* Allocate space for the ss element to element block parameter index array */
  if (!(ss_parm_ndx=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(elem_blk_parms);
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
"Error: failed to allocate space for side set elem parms index for file id %d"
,
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
    return (EX_FATAL);
  }


  /* Allocate space for the ss element to node list index array */
  if (!(ss_elem_node_ndx=static_cast<int*>(malloc(tot_num_ss_elem*sizeof(int)))))
  {
    free(ss_parm_ndx);
    free(elem_blk_parms);
    free(elem_blk_ids);
    free(ss_elem_ndx);
    free(side_set_side_list);
    free(side_set_elem_list);
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
"Error: failed to allocate space for side set elem to node index for file id %d",
            exoid);
    ex_err("ex_get_side_set_node_list",errmsg,exerrval);
           
    return (EX_FATAL);
  }

/* Build side set element to node list index and side set element 
   parameter index.
*/
  node_ctr = 0;
  for (i=0;i<tot_num_ss_elem;i++)
  {
    for (j=0; j<num_elem_blks; j++)
    {
      if (elem_blk_parms[j].elem_type_val != '\0')
      if (side_set_elem_list[i] <= elem_blk_parms[j].elem_ctr)
        break;
    }

    if (j >= num_elem_blks)
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
             "Error: Invalid element number %d found in side set %d in file %d",
              side_set_elem_list[i], side_set_id, exoid);
      free(ss_parm_ndx);
      free(ss_elem_node_ndx);
      free(elem_blk_parms);
      free(elem_blk_ids);
      free(ss_elem_ndx);
      free(side_set_side_list);
      free(side_set_elem_list);
      ex_err("ex_get_side_set_node_list",errmsg,EX_MSG);
      return (EX_FATAL);
    }

    ss_parm_ndx[i] = j; /* assign parameter block index */
    ss_elem_node_ndx[i] = node_ctr;     /* assign node list index */

    /* Update node_ctr (which points to next node in chain */

    /* WEDGEs with 3 node sides (side 4 or 5) are special cases */
    if (elem_blk_parms[j].elem_type_val == WEDGE &&
        (side_set_side_list[i] == 4 || side_set_side_list[i] == 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 6)
        node_ctr += 3;  /* 3 node side */
      else
        node_ctr += 6;  /* 6 node side */
    }
    /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */
    else if (elem_blk_parms[j].elem_type_val == PYRAMID &&
             (side_set_side_list[i] < 5))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 5)
        node_ctr += 3;  /* 3 node side */
      else
        node_ctr += 6;  /* 6 node side */
    }
    /* side numbers 3,4,5,6 for SHELLs are also special */
    else if (elem_blk_parms[j].elem_type_val == SHELL &&
        (side_set_side_list[i] > 2 ))
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 4)
        node_ctr += 2;  /* 2 node side */
      else
        node_ctr += 3;  /* 3 node side */
    }
    /* side numbers 3,4,5 for 3d TRIs are also special */
    else if (elem_blk_parms[j].elem_type_val == TRIANGLE &&
             ndim == 3 &&
             side_set_side_list[i] > 2 )
    {
      if (elem_blk_parms[j].num_nodes_per_elem == 3)  /* 3-node TRI */
        node_ctr += 2;  /* 2 node side */
      else   /* 6-node TRI */
        node_ctr += 3;  /* 3 node side */
    }
    else /* all other element types */
      node_ctr += elem_blk_parms[j].num_nodes_per_side;
  }

  /* All setup, ready to go ... */

  elem_ctr=0;

  for (j=0; j < tot_num_ss_elem; j++)
  {

    if (side_set_elem_list[ss_elem_ndx[j]] > elem_ctr)
    {
      /* release connectivity array space and get next one */
      if (elem_ctr > 0)
      {
        free(connect);
      }

      /* Allocate space for the connectivity array for new element block */
      if (!(connect=static_cast<int*>(malloc(elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk*
                           elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem*
					     (int)sizeof(int)))))
      {
        free(elem_blk_parms);
        free(elem_blk_ids);
        free(ss_elem_ndx);
        free(ss_elem_node_ndx);
        free(ss_parm_ndx);
        free(side_set_side_list);
        free(side_set_elem_list);
        exerrval = EX_MEMFAIL;
        sprintf(errmsg,
        "Error: failed to allocate space for connectivity array for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return (EX_FATAL);
      }

      /* get connectivity array */
      if (ex_get_elem_conn(
                        exoid,
                        elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id,
                        connect) == -1)
      {
        free(connect);
        free(elem_blk_parms);
        free(elem_blk_ids);
        free(ss_elem_ndx);
        free(ss_elem_node_ndx);
        free(ss_parm_ndx);
        free(side_set_side_list);
        free(side_set_elem_list);
        sprintf(errmsg,
        "Error: failed to allocate space for connectivity array for file id %d",
                exoid);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return (EX_FATAL);
      }
      elem_ctr = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr;
    }
/*  For each side in side set, use the appropriate lookup table to  
      determine the nodes from the connect array. */

    elem_num = side_set_elem_list[ss_elem_ndx[j]]-1;/* element number 0-based*/
    /* calculate the relative element number position in it's block*/

    elem_num_pos = elem_num - 
                  (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr -
                   elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk);

    /* calculate the beginning of the node list for this element by
         using the ss_elem_node_ndx index into the side_sets_node_index
         and adding the element number position * number of nodes per elem */

    num_nodes_per_elem = 
               elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem;
    node_pos = ss_elem_node_ndx[ss_elem_ndx[j]];
    connect_offset = num_nodes_per_elem*elem_num_pos;
    side_num = side_set_side_list[ss_elem_ndx[j]]-1;

    switch (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type_val)
    {
      case CIRCLE:
      case SPHERE:
      { /* Note: no side-node lookup table is used for this simple case */
        side_set_node_list[node_pos] = connect[connect_offset];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 1;   /* 1 node object */
        break;
      }
      case TRUSS:
      case BEAM:
      { /* Note: no side-node lookup table is used for this simple case */
        side_set_node_list[node_pos] = connect[connect_offset];
        side_set_node_list[node_pos+1] = connect[connect_offset+1];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
        if (num_nodes_per_elem > 2)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
          side_set_node_list[node_pos+2] = connect[connect_offset+2];
        }
        break;
      }
      case TRIANGLE:
      {
        if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid triangle edge number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        if (ndim == 2)   /* 2d TRIs */
        {
          side_set_node_list[node_pos] = 
            connect[connect_offset+tri_table[side_num][0]-1];
          side_set_node_list[node_pos+1] = 
            connect[connect_offset+tri_table[side_num][1]-1];
          side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
          if (num_nodes_per_elem > 3)   /* 6-node TRI  */
          {
            side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
            side_set_node_list[node_pos+2] = 
              connect[connect_offset+tri_table[side_num][2]-1];
          }
        }
        else if (ndim == 3)  /* 3d TRIs */
        {
          side_set_node_list[node_pos] = 
            connect[connect_offset+tri3_table[side_num][0]-1];
          side_set_node_list[node_pos+1] = 
            connect[connect_offset+tri3_table[side_num][1]-1];
          side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
          if (side_num+1 <= 2)  /* 3- or 6-node face */
          {
            if (num_nodes_per_elem == 3)  /* 3-node face */
            {
              side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
              side_set_node_list[node_pos+2] = 
                connect[connect_offset+tri3_table[side_num][2]-1];
            }
            else   /* 6-node face */
            {
              side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */
              side_set_node_list[node_pos+2] = 
                connect[connect_offset+tri3_table[side_num][2]-1];
              side_set_node_list[node_pos+3] = 
                connect[connect_offset+tri3_table[side_num][3]-1];
              side_set_node_list[node_pos+4] = 
                connect[connect_offset+tri3_table[side_num][4]-1];
              side_set_node_list[node_pos+5] = 
                connect[connect_offset+tri3_table[side_num][5]-1];
            }
          }
          else /* 2- or 3-node edge */
          {
            if (num_nodes_per_elem > 3)  /* 3-node edge */
            {
              side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
              side_set_node_list[node_pos+2] = 
                connect[connect_offset+tri3_table[side_num][2]-1];
            }
          }
        }
        break;
      }
      case QUAD:
      {
        if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid quad edge number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }
        
        side_set_node_list[node_pos] = 
          connect[connect_offset+quad_table[side_num][0]-1];
        side_set_node_list[node_pos+1] = 
          connect[connect_offset+quad_table[side_num][1]-1];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
        if (num_nodes_per_elem > 5)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */
          side_set_node_list[node_pos+2] = 
            connect[connect_offset+quad_table[side_num][2]-1];
        }
        break;
      }
      case SHELL:
      {
        if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid shell face number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        side_set_node_list[node_pos] = 
          connect[connect_offset+shell_table[side_num][0]-1];
        side_set_node_list[node_pos+1] = 
          connect[connect_offset+shell_table[side_num][1]-1];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 2;   /* 2 node object */
        if (num_nodes_per_elem > 2) /*** KLUDGE for 2D shells ***/
        {
          if (side_num+1 <= 2)  /* 4-node face */
          {
            side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node object */
            side_set_node_list[node_pos+2] = 
              connect[connect_offset+shell_table[side_num][2]-1];
            side_set_node_list[node_pos+3] = 
              connect[connect_offset+shell_table[side_num][3]-1];
          }
        }
        if (num_nodes_per_elem == 8)
        {
          if (side_num+1 <= 2)  /* 8-node face */
          {
            side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
            side_set_node_list[node_pos+4] = 
              connect[connect_offset+shell_table[side_num][4]-1];
            side_set_node_list[node_pos+5] = 
              connect[connect_offset+shell_table[side_num][5]-1];
            side_set_node_list[node_pos+6] = 
              connect[connect_offset+shell_table[side_num][6]-1];
            side_set_node_list[node_pos+7] = 
              connect[connect_offset+shell_table[side_num][7]-1];
          }
          else 
          {
            side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node edge */
            side_set_node_list[node_pos+2] = 
              connect[connect_offset+shell_table[side_num][2]-1];
          }
        }
        break;
      }
      case TETRA:
      {
        if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid tetra face number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        side_set_node_list[node_pos] = 
          connect[connect_offset+tetra_table[side_num][0]-1];
        side_set_node_list[node_pos+1] = 
          connect[connect_offset+tetra_table[side_num][1]-1];
        side_set_node_list[node_pos+2] = 
          connect[connect_offset+tetra_table[side_num][2]-1];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node object */
        if (num_nodes_per_elem == 8)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node object */
          side_set_node_list[node_pos+3] = 
            connect[connect_offset+tetra_table[side_num][3]-1];
        }
        else if (num_nodes_per_elem > 8)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */
          side_set_node_list[node_pos+3] = 
            connect[connect_offset+tetra_table[side_num][3]-1];
          side_set_node_list[node_pos+4] = 
            connect[connect_offset+tetra_table[side_num][4]-1];
          side_set_node_list[node_pos+5] = 
            connect[connect_offset+tetra_table[side_num][5]-1];
        }
        break;
      }
      case WEDGE:
      {
        if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid wedge face number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        side_set_node_list[node_pos++] = 
          connect[connect_offset+wedge_table[side_num][0]-1];
        side_set_node_list[node_pos++] = 
          connect[connect_offset+wedge_table[side_num][1]-1];
        side_set_node_list[node_pos++] = 
          connect[connect_offset+wedge_table[side_num][2]-1];

        if (wedge_table[side_num][3] == 0) { /* degenerate side? */
          side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node side */
        }
        else
        {
          side_set_node_list[node_pos++] =
            connect[connect_offset+wedge_table[side_num][3]-1];
          side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node side */
        }


        if (num_nodes_per_elem > 6)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
          side_set_node_list[node_pos++] = 
            connect[connect_offset+wedge_table[side_num][4]-1];
          side_set_node_list[node_pos++] = 
            connect[connect_offset+wedge_table[side_num][5]-1];
          side_set_node_list[node_pos++] = 
            connect[connect_offset+wedge_table[side_num][6]-1];

          if (wedge_table[side_num][7] == 0) /* degenerate side? */
            side_set_node_cnt_list[ss_elem_ndx[j]] = 6;   /* 6 node side */
          else
          {
            side_set_node_list[node_pos++] =
              connect[connect_offset+wedge_table[side_num][7]-1];
            side_set_node_cnt_list[ss_elem_ndx[j]] = 8;   /* 8 node side */
          }
        }
        break;
      }
      case PYRAMID:
      {
        if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid pyramid face number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        side_set_node_list[node_pos++] = 
          connect[connect_offset+pyramid_table[side_num][0]-1];
        side_set_node_list[node_pos++] = 
          connect[connect_offset+pyramid_table[side_num][1]-1];
        side_set_node_list[node_pos++] = 
          connect[connect_offset+pyramid_table[side_num][2]-1];

        if (pyramid_table[side_num][3] == 0) { /* degenerate side? */
          side_set_node_cnt_list[ss_elem_ndx[j]] = 3;   /* 3 node side */
        }
        else
        {
          side_set_node_list[node_pos++] =
            connect[connect_offset+pyramid_table[side_num][3]-1];
          side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node side */
        }


        if (num_nodes_per_elem > 5)
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
          side_set_node_list[node_pos++] = 
            connect[connect_offset+pyramid_table[side_num][4]-1];
          side_set_node_list[node_pos++] = 
            connect[connect_offset+pyramid_table[side_num][5]-1];
          side_set_node_list[node_pos++] = 
            connect[connect_offset+pyramid_table[side_num][6]-1];

          if (pyramid_table[side_num][7] == 0) /* degenerate side? */
            side_set_node_cnt_list[ss_elem_ndx[j]] = 6;   /* 6 node side */
          else
          {
            side_set_node_list[node_pos++] =
              connect[connect_offset+pyramid_table[side_num][7]-1];
            side_set_node_cnt_list[ss_elem_ndx[j]] = 8;   /* 8 node side */
          }
        }
        break;
      }
      case HEX:
      {
        if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */
        {
          exerrval = EX_BADPARAM;
          sprintf(errmsg,
                 "Error: Invalid hex face number %d in file id %d",
                  side_num+1, exoid);
          ex_err("ex_get_side_set_node_list",errmsg,exerrval);
          free(connect);
          free(elem_blk_parms);
          free(elem_blk_ids);
          free(ss_elem_ndx);
          free(ss_elem_node_ndx);
          free(ss_parm_ndx);
          free(side_set_side_list);
          free(side_set_elem_list);
          return(EX_FATAL);
        }

        side_set_node_list[node_pos] = 
          connect[connect_offset+hex_table[side_num][0]-1];
        side_set_node_list[node_pos+1] = 
          connect[connect_offset+hex_table[side_num][1]-1];
        side_set_node_list[node_pos+2] = 
          connect[connect_offset+hex_table[side_num][2]-1];
        side_set_node_list[node_pos+3] = 
          connect[connect_offset+hex_table[side_num][3]-1];
        side_set_node_cnt_list[ss_elem_ndx[j]] = 4;   /* 4 node object */
        if (num_nodes_per_elem > 12)   /* more nodes than HEXSHELL */
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */
          side_set_node_list[node_pos+4] = 
            connect[connect_offset+hex_table[side_num][4]-1];
          side_set_node_list[node_pos+5] = 
            connect[connect_offset+hex_table[side_num][5]-1];
          side_set_node_list[node_pos+6] = 
            connect[connect_offset+hex_table[side_num][6]-1];
          side_set_node_list[node_pos+7] = 
            connect[connect_offset+hex_table[side_num][7]-1];
        }
        if (num_nodes_per_elem == 27)                 /* 27-node brick */
        {
          side_set_node_cnt_list[ss_elem_ndx[j]] = 9; /* 9 node object */
          side_set_node_list[node_pos+8] = 
            connect[connect_offset+hex_table[side_num][8]-1];
        }
        break;
      }
      default:
      {
        exerrval = EX_BADPARAM;
        sprintf(errmsg,
               "Error: %s is an unsupported element type",
                elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type);
        ex_err("ex_get_side_set_node_list",errmsg,exerrval);
        return(EX_FATAL);
      }
    }
  }


  /* All done: release connectivity array space, element block ids array,
     element block parameters array, and side set element index array */
  free(connect);
  free(ss_parm_ndx);
  free(elem_blk_ids);
  free(elem_blk_parms);
  free(ss_elem_ndx);
  free(ss_elem_node_ndx);
  free(side_set_side_list);
  free(side_set_elem_list);

  return(EX_NOERR);
}
/*! \undoc */
int ex_get_concat_side_set_node_count(int exoid,
				      int *side_set_node_cnt_list)
{
  size_t m;
  int ii, i, j, iss, ioff; 
  ex_entity_id side_set_id;
  int  num_side_sets, num_elem_blks, num_df, ndim;
  int64_t tot_num_elem = 0, tot_num_ss_elem = 0, side, elem;
  void_int *elem_blk_ids       = NULL;
  void_int *side_set_ids       = NULL;
  void_int *ss_elem_ndx        = NULL;
  void_int *side_set_elem_list = NULL;
  void_int *side_set_side_list = NULL;
  size_t elem_ctr;
  int int_size, ids_size;
  int status;
  
  struct elem_blk_parm  *elem_blk_parms;

  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  /* first check if any side sets are specified */
  /* inquire how many side sets have been stored */
  num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
  if (num_side_sets < 0) {
    sprintf(errmsg,
           "Error: failed to get number of side sets in file id %d",exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  if (num_side_sets == 0) {
    sprintf(errmsg,
           "Warning: no side sets defined in file id %d",exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,EX_WARN);
    return(EX_WARN);
  }

  num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
  if (num_elem_blks < 0) {
    sprintf(errmsg,
           "Error: failed to get number of element blocks in file id %d",exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
  if (tot_num_elem < 0) {
    sprintf(errmsg,
           "Error: failed to get total number of elements in file id %d",exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    return(EX_FATAL);
  }

  /* get the dimensionality of the coordinates;  this is necessary to
     distinguish between 2d TRIs and 3d TRIs */
  ndim = ex_inquire_int(exoid, EX_INQ_DIM);
  if (ndim < 0) {
    sprintf(errmsg,
           "Error: failed to get dimensionality in file id %d",exoid);
    ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval);
    return(EX_FATAL);
  }

  int_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_BULK_INT64_API)
    int_size = sizeof(int64_t);
  
  /* Allocate space for the element block ids */
  ids_size = sizeof(int);
  if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
    ids_size = sizeof(int64_t);
  }

  if (!(elem_blk_ids=malloc(num_elem_blks*ids_size))) {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
            "Error: failed to allocate space for element block ids for file id %d",
            exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    goto error_ret;
  }

  if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids) == -1) {
    sprintf(errmsg,
            "Error: failed to get element block ids in file id %d",
            exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,EX_MSG);
    return(EX_FATAL);
  } 

  /* Allocate space for the element block params */
  if (!(elem_blk_parms=malloc(num_elem_blks*sizeof(struct elem_blk_parm)))) {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
      "Error: failed to allocate space for element block params for file id %d",
            exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    goto error_ret;
  }

  elem_ctr = 0;
  for (i=0; i<num_elem_blks; i++)
  {
    ex_entity_id id;
    ex_block block;
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      id = ((int64_t*)elem_blk_ids)[i];
    } else {
      id = ((int*)elem_blk_ids)[i];
    }

    /* read in an element block parameter */
    block.type = EX_ELEM_BLOCK;
    block.id = id;

    /* read in an element block parameter */
    if ((ex_get_block_param (exoid, &block)) == -1) {
      sprintf(errmsg,
             "Error: failed to get element block  %"PRId64" parameters in file id %d",
              block.id, exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,EX_MSG);
      return(EX_FATAL);
    }

    elem_blk_parms[i].num_elem_in_blk = block.num_entry;
    elem_blk_parms[i].num_nodes_per_elem = block.num_nodes_per_entry;
    elem_blk_parms[i].num_attr = block.num_attribute;

    for (m=0; m < strlen(block.topology); m++) {
      elem_blk_parms[i].elem_type[m] = toupper(block.topology[m]);
    }
    elem_blk_parms[i].elem_type[m] = '\0';

    if (strncmp(elem_blk_parms[i].elem_type,"CIRCLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_CIRCLE;
      elem_blk_parms[i].num_sides = 1;
      elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SPHERE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_SPHERE;
      elem_blk_parms[i].num_sides = 1;
        elem_blk_parms[i].num_nodes_per_side[0] = 1;
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"QUAD",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_QUAD;
      elem_blk_parms[i].num_sides = 4;
      if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 5) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 9 ||
                 elem_blk_parms[i].num_nodes_per_elem == 8) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TRIANGLE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TRIANGLE;
      if (ndim == 2) { /* 2d TRIs */
        elem_blk_parms[i].num_sides = 3;
        if (elem_blk_parms[i].num_nodes_per_elem == 3) {
          elem_blk_parms[i].num_nodes_per_side[0] = 2;
          elem_blk_parms[i].num_nodes_per_side[1] = 2;
          elem_blk_parms[i].num_nodes_per_side[2] = 2;
        } else if (elem_blk_parms[i].num_nodes_per_elem == 6) {
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
          elem_blk_parms[i].num_nodes_per_side[1] = 3;
          elem_blk_parms[i].num_nodes_per_side[2] = 3;
        }
      } else if (ndim == 3) { /* 3d TRIs -- triangular shell*/
        elem_blk_parms[i].num_sides = 5; /* 2 Faces and 3 Edges */
        if (elem_blk_parms[i].num_nodes_per_elem == 3) {
          elem_blk_parms[i].num_nodes_per_side[0] = 3;
          elem_blk_parms[i].num_nodes_per_side[1] = 3;
          elem_blk_parms[i].num_nodes_per_side[2] = 2;
          elem_blk_parms[i].num_nodes_per_side[3] = 2;
          elem_blk_parms[i].num_nodes_per_side[4] = 2;
        } else if (elem_blk_parms[i].num_nodes_per_elem == 6) {
          elem_blk_parms[i].num_nodes_per_side[0] = 6;
          elem_blk_parms[i].num_nodes_per_side[1] = 6;
          elem_blk_parms[i].num_nodes_per_side[2] = 3;
          elem_blk_parms[i].num_nodes_per_side[3] = 3;
          elem_blk_parms[i].num_nodes_per_side[4] = 3;
        } else {
          EL_NODE_COUNT_ERROR;
        }
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"SHELL",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_SHELL;

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {/* KLUDGE for 2D Shells*/
        elem_blk_parms[i].num_sides = 2; 
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_sides = 6;  /* 2 Faces, 4 Edges */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 2;
        elem_blk_parms[i].num_nodes_per_side[3] = 2;
        elem_blk_parms[i].num_nodes_per_side[4] = 2;
        elem_blk_parms[i].num_nodes_per_side[5] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 8 ||
                 elem_blk_parms[i].num_nodes_per_elem == 9) {
        elem_blk_parms[i].num_sides = 6;  /* 2 Faces, 4 Edges */
        elem_blk_parms[i].num_nodes_per_side[0] =
          elem_blk_parms[i].num_nodes_per_elem; /* 8 or 9 */
        elem_blk_parms[i].num_nodes_per_side[1] =
          elem_blk_parms[i].num_nodes_per_elem; /* 8 or 9 */
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 3;
        elem_blk_parms[i].num_nodes_per_side[5] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"HEX",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_HEX;
      elem_blk_parms[i].num_sides = 6;  
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 8) {  /* 8-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 9) { /* 9-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 12) { /* HEXSHELLS */
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
        elem_blk_parms[i].num_nodes_per_side[5] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 20) { /* 20-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
        elem_blk_parms[i].num_nodes_per_side[1] = 8;
        elem_blk_parms[i].num_nodes_per_side[2] = 8;
        elem_blk_parms[i].num_nodes_per_side[3] = 8;
        elem_blk_parms[i].num_nodes_per_side[4] = 8;
        elem_blk_parms[i].num_nodes_per_side[5] = 8;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 27) { /* 27-node bricks */
        elem_blk_parms[i].num_nodes_per_side[0] = 9;
        elem_blk_parms[i].num_nodes_per_side[1] = 9;
        elem_blk_parms[i].num_nodes_per_side[2] = 9;
        elem_blk_parms[i].num_nodes_per_side[3] = 9;
        elem_blk_parms[i].num_nodes_per_side[4] = 9;
        elem_blk_parms[i].num_nodes_per_side[5] = 9;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"TETRA",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TETRA;
      elem_blk_parms[i].num_sides = 4;  
      /* determine side set node stride */
      if (elem_blk_parms[i].num_nodes_per_elem == 4) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 8) {
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 10) {
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"WEDGE",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_WEDGE;
      elem_blk_parms[i].num_sides = 5;  
      if (elem_blk_parms[i].num_nodes_per_elem == 6) {
        elem_blk_parms[i].num_nodes_per_side[0] = 4;
        elem_blk_parms[i].num_nodes_per_side[1] = 4;
        elem_blk_parms[i].num_nodes_per_side[2] = 4;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 3;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 15){
        elem_blk_parms[i].num_nodes_per_side[0] = 8;
        elem_blk_parms[i].num_nodes_per_side[1] = 8;
        elem_blk_parms[i].num_nodes_per_side[2] = 8;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 6;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"PYRAMID",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_PYRAMID;
      elem_blk_parms[i].num_sides = 5;  
      if (elem_blk_parms[i].num_nodes_per_elem == 5) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
        elem_blk_parms[i].num_nodes_per_side[2] = 3;
        elem_blk_parms[i].num_nodes_per_side[3] = 3;
        elem_blk_parms[i].num_nodes_per_side[4] = 4;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 13){
        elem_blk_parms[i].num_nodes_per_side[0] = 6;
        elem_blk_parms[i].num_nodes_per_side[1] = 6;
        elem_blk_parms[i].num_nodes_per_side[2] = 6;
        elem_blk_parms[i].num_nodes_per_side[3] = 6;
        elem_blk_parms[i].num_nodes_per_side[4] = 8;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if (strncmp(elem_blk_parms[i].elem_type,"BEAM",3) == 0)
    {
      elem_blk_parms[i].elem_type_val = EX_EL_BEAM;
      elem_blk_parms[i].num_sides = 2;  

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 3){
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    else if ( (strncmp(elem_blk_parms[i].elem_type,"TRUSS",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"BAR",3) == 0) ||
              (strncmp(elem_blk_parms[i].elem_type,"EDGE",3) == 0) )
    {
      elem_blk_parms[i].elem_type_val = EX_EL_TRUSS;
      elem_blk_parms[i].num_sides = 2;  

      if (elem_blk_parms[i].num_nodes_per_elem == 2) {
        elem_blk_parms[i].num_nodes_per_side[0] = 2;
        elem_blk_parms[i].num_nodes_per_side[1] = 2;
      } else if (elem_blk_parms[i].num_nodes_per_elem == 3) {
        elem_blk_parms[i].num_nodes_per_side[0] = 3;
        elem_blk_parms[i].num_nodes_per_side[1] = 3;
      } else {
        EL_NODE_COUNT_ERROR;
      }
    }
    /* Used for an empty block in a parallel decomposition */
    else if (strncmp(elem_blk_parms[i].elem_type,"NULL",3) == 0) {
      elem_blk_parms[i].elem_type_val = EX_EL_NULL_ELEMENT;
      elem_blk_parms[i].num_sides = 0;  
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
      elem_blk_parms[i].num_elem_in_blk = 0;
    } else {
      /* unsupported element type; no problem if no sides specified for
         this element block */
      elem_blk_parms[i].elem_type_val = EX_EL_UNK;
      elem_blk_parms[i].num_sides = 0;  
      elem_blk_parms[i].num_nodes_per_side[0] = 0;
    }

    elem_blk_parms[i].elem_blk_id = id;    /* save id */
    elem_ctr += elem_blk_parms[i].num_elem_in_blk;
    elem_blk_parms[i].elem_ctr = elem_ctr;      /* save elem number max */
  }


  /* Finally... Create the list of node counts for each face in the
   * side set.
   */
  /* Allocate space for the sideset ids */
  if (!(side_set_ids=malloc(num_side_sets*ids_size))) {
    exerrval = EX_MEMFAIL;
    sprintf(errmsg,
            "Error: failed to allocate space for side set ids for file id %d",
            exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
    goto error_ret;
  }

  if (ex_get_ids(exoid, EX_SIDE_SET, side_set_ids) == -1) {
    sprintf(errmsg,
            "Error: failed to get side set ids in file id %d",
            exoid);
    ex_err("ex_get_concat_side_set_node_count",errmsg,EX_MSG);
    goto error_ret;
  } 

  /* Lookup index of side set id in VAR_SS_IDS array */
  ioff = 0;
  for (iss=0; iss<num_side_sets; iss++) {
    if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
      side_set_id = ((int64_t*)side_set_ids)[iss];
    } else {
      side_set_id = ((int*)side_set_ids)[iss];
    }
    
    /* First determine the  # of elements in the side set*/
    if (int_size == sizeof(int64_t)) {
      status = ex_get_set_param(exoid,EX_SIDE_SET, side_set_id,&tot_num_ss_elem,&num_df);
    } else {
      int tot, df;
      status = ex_get_set_param(exoid,EX_SIDE_SET, side_set_id,&tot,&df);
      tot_num_ss_elem = tot;
      num_df = df;
    }

    if (status != EX_NOERR) {
      sprintf(errmsg,
	      "Error: failed to get number of elements in side set  %"PRId64" in file id %d",
	      side_set_id, exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
      goto error_ret;
    }
    
    if (tot_num_ss_elem == 0)
      continue;
   
    /* Allocate space for the side set element list */
    if (!(side_set_elem_list=malloc(tot_num_ss_elem*int_size))) {
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set element list for file id %d",
	      exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
      goto error_ret;
    }
    
    /* Allocate space for the side set side list */
    if (!(side_set_side_list=malloc(tot_num_ss_elem*int_size))) {
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set side list for file id %d",
	      exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
      goto error_ret;
    }
    
    if (ex_get_set(exoid, EX_SIDE_SET, side_set_id, 
		   side_set_elem_list, side_set_side_list) == -1) {
      sprintf(errmsg,
	      "Error: failed to get side set  %"PRId64" in file id %d",
	      side_set_id, exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
      goto error_ret;
    }
    
    /* Allocate space for the ss element index array */
    if (!(ss_elem_ndx=malloc(tot_num_ss_elem*int_size))) {
      exerrval = EX_MEMFAIL;
      sprintf(errmsg,
	      "Error: failed to allocate space for side set elem sort array for file id %d",
	      exoid);
      ex_err("ex_get_concat_side_set_node_count",errmsg,exerrval);
      goto error_ret;
    }
    
    /* Sort side set element list into index array  - non-destructive */
    if (int_size == sizeof(int64_t)) {
      /* Sort side set element list into index array  - non-destructive */
      int64_t *elems = (int64_t*)ss_elem_ndx;
      for (i=0;i<tot_num_ss_elem;i++) {
	elems[i] = i; /* init index array to current position */
      }
      ex_iqsort64(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
    } else {
      /* Sort side set element list into index array  - non-destructive */
      int *elems = (int*)ss_elem_ndx;
      for (i=0;i<tot_num_ss_elem;i++) {
	elems[i] = i; /* init index array to current position */
      }
      ex_iqsort(side_set_elem_list, ss_elem_ndx,tot_num_ss_elem);
    }
    
    j = 0; /* The current element block... */
    for (ii=0;ii<tot_num_ss_elem;ii++) {
      
      int64_t elem_ndx;
      if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
	elem_ndx = ((int64_t*)ss_elem_ndx)[ii];
	elem     = ((int64_t*)side_set_elem_list)[elem_ndx];
	side     = ((int64_t*)side_set_side_list)[elem_ndx]-1;
      } else {
	elem_ndx = ((int*)ss_elem_ndx)[ii];
	elem     = ((int*)side_set_elem_list)[elem_ndx];
	side     = ((int*)side_set_side_list)[elem_ndx]-1;
      }
      
      /*
       * Since the elements are being accessed in sorted, order, the
       * block that contains the elements must progress sequentially
       * from block 0 to block[num_elem_blks-1]. Once we find an element
       * not in this block, find a following block that contains it...
       */       
      for ( ; j<num_elem_blks; j++) {
	if (elem <= elem_blk_parms[j].elem_ctr) {
	  break;
	}
      }
      
      if (j < num_elem_blks) {
	assert(side < elem_blk_parms[j].num_sides);  
	side_set_node_cnt_list[elem_ndx+ioff] = elem_blk_parms[j].num_nodes_per_side[side];
      } else {
	exerrval = EX_BADPARAM;
	sprintf(errmsg,
		"Error: Invalid element number  %"PRId64" found in side set  %"PRId64" in file %d",
		elem, side_set_id, exoid);
	ex_err("ex_get_concat_side_set_node_count",errmsg,EX_MSG);
	goto error_ret;
      }
    }
    ss_elem_ndx        = safe_free(ss_elem_ndx);
    side_set_elem_list = safe_free(side_set_elem_list);
    side_set_side_list = safe_free(side_set_side_list);
    ioff += tot_num_ss_elem;
  }
    
  /* All done: release allocated memory */
  safe_free(elem_blk_ids);
  safe_free(side_set_ids);

  return(EX_NOERR);

 error_ret:
  safe_free(elem_blk_ids);
  safe_free(side_set_ids);
  safe_free(ss_elem_ndx);
  safe_free(side_set_elem_list);
  safe_free(side_set_side_list);
  return (EX_FATAL);
}