/* --------------------------------------------------------------------  */
/*                          CALCULIX                                     */
/*                   - GRAPHICAL INTERFACE -                             */
/*                                                                       */
/*     A 3-dimensional pre- and post-processor for finite elements       */
/*              Copyright (C) 1996 Klaus Wittig                          */
/*                                                                       */
/*     This program is free software; you can redistribute it and/or     */
/*     modify it under the terms of the GNU General Public License as    */
/*     published by the Free Software Foundation; version 2 of           */
/*     the License.                                                      */
/*                                                                       */
/*     This program is distributed in the hope that it will be useful,   */
/*     but WITHOUT ANY WARRANTY; without even the implied warranty of    */ 
/*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the      */
/*     GNU General Public License for more details.                      */
/*                                                                       */
/*     You should have received a copy of the GNU General Public License */
/*     along with this program; if not, write to the Free Software       */
/*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.         */
/* --------------------------------------------------------------------  */


/* TODO */
/*
 Bugs:
*/

#include <cgx.h>
#include  <time.h>

#define     TEST            0       /* debugging */


/* data */
extern int     num_onodmax;          /* max-node-nr-of-original-nodes (nodes from input-file) */
extern int       num_onod;          /* nr-of-original-nodes (nodes from input-file) */
extern int       num_olc;           /* nr-of-original-loadcases (lc from input-file) */

extern Summen    anz[1];
extern Nodes     *node;
extern Elements  *e_enqire;         /* elem-array by elem-number instead of elem[index]... */
extern Datasets  *lcase;
extern NodeBlocks *nBlock;

extern double     *value_n;
extern double     *vp;
extern Nodes     *n_anim;
extern Edges     *edge;             /* model-edges           */
extern Scale     scale[1];
extern Faces     *face;

extern Sets      *set;

extern int       lc;                                      /* aktiver Dataset (4C, 5C)*/
extern int       elemMat[99];      /*  Material Numbers, Number of Materials stored in elemMat[0] */

/* for CFD-meshing */
extern double pref, tref, R_GAS;

int setall;

/* find the element face */
int getFaceNr(int elem_nr, int *nod)
{
  int j,k,n, f[6], ni[8];

  n=0;
  if((e_enqire[elem_nr].type==1)||(e_enqire[elem_nr].type==4)||(e_enqire[elem_nr].type==2)||(e_enqire[elem_nr].type==5))
  {
    for(j=0; j<8; j++) 
      for(k=0; k<4; k++)
        if(e_enqire[elem_nr].nod[j]==nod[k])
          ni[n++]=j+1;
    if (n==4)
    {
      /* check which sides are involved */
      for (j=0; j<6; j++) f[j]=0;
      for (j=0; j<4; j++)
      {
        if ((ni[j]==1)||(ni[j]==2)||(ni[j]==3)||(ni[j]==4)) f[0]++;
        if ((ni[j]==5)||(ni[j]==8)||(ni[j]==7)||(ni[j]==6)) f[1]++;
        if ((ni[j]==1)||(ni[j]==5)||(ni[j]==6)||(ni[j]==2)) f[2]++;
        if ((ni[j]==2)||(ni[j]==6)||(ni[j]==7)||(ni[j]==3)) f[3]++;
        if ((ni[j]==3)||(ni[j]==7)||(ni[j]==8)||(ni[j]==4)) f[4]++;
        if ((ni[j]==4)||(ni[j]==8)||(ni[j]==5)||(ni[j]==1)) f[5]++;
      }
    }
    for (j=0; j<6; j++){ if(f[j]==4) return(j); }
  }
  else if((e_enqire[elem_nr].type==3)||(e_enqire[elem_nr].type==6))
  {
    for(j=0; j<4; j++) 
      for(k=0; k<3; k++)
        if(e_enqire[elem_nr].nod[j]==nod[k])
          ni[n++]=j+1;
    if (n==3)
    {
      /* check which sides are involved */
      for (j=0; j<4; j++) f[j]=0;
      for (j=0; j<3; j++)
      {
        if ((ni[j]==1)||(ni[j]==3)||(ni[j]==2)) f[0]++;
        if ((ni[j]==1)||(ni[j]==2)||(ni[j]==4)) f[1]++;
        if ((ni[j]==2)||(ni[j]==3)||(ni[j]==4)) f[2]++;
        if ((ni[j]==3)||(ni[j]==1)||(ni[j]==4)) f[3]++;
      }
    }
    for (j=0; j<4; j++){ if(f[j]==3) return(j); }
  }
  return(-1);
}



/* --- define the surfaces of the part which are derived from the volume-elements -- */
void makeSurfaces()
{
  int  i,j,k,n,ne, ns, numFaces, type, num_etype[13];
  int  *pfaces, *pfacesN, ipuf, nf=0;
  static Elements *elem[13];

  /* free all faces */
  for(i=0; i<anz->f; i++)
  {
    if (face[i].type == 7)       nf=1;  /* TRI3  */
    else if (face[i].type == 8)  nf=4; /* TRI6  */
    else if (face[i].type == 9)  nf=2; /* QUAD4 */
    else if (face[i].type == 10) nf=8; /* QUAD8 */
    else if (face[i].type == 11) nf=1; /* BEAM */
    else if (face[i].type == 12) nf=1; /* BEAM3 */
    if(face[i].side!=NULL)
    {
      for(k=0; k<nf; k++) free(face[i].side[k]);
      free(face[i].side);
      face[i].side=NULL;
    }
  }

  anz->g=0;
  anz->f=0;
  for (i=0; i<13; i++) { num_etype[i]=0; elem[i]=NULL; } 

  /* first sort all elements */
  for (i=0; i<anz->e; i++)  
  {
    type=e_enqire[ e_enqire[i].nr ].type;
    if(type>12) { printf("ERROR unknown element-type:%d\n", type); exit(1); }
    if((elem[type]=(Elements *)realloc( (Elements *)elem[type], (num_etype[type]+2)*sizeof(Elements)))==NULL )
    printf("\n\n ERROR: realloc failed\n\n") ;
    elem[type][num_etype[type]].nr   =e_enqire[i].nr;
    elem[type][num_etype[type]].group=e_enqire[ e_enqire[i].nr ].group ;
    elem[type][num_etype[type]].mat  =e_enqire[ e_enqire[i].nr ].mat   ;
    elem[type][num_etype[type]].type =e_enqire[ e_enqire[i].nr ].type  ;
    elem[type][num_etype[type]].attr =e_enqire[ e_enqire[i].nr ].attr  ;
    ipuf=0;
    if (elem[type][num_etype[type]].type == 1) ipuf = 8;  /* HEXA8 */
    if (elem[type][num_etype[type]].type == 2) ipuf = 6;  /* PENTA6 */
    if (elem[type][num_etype[type]].type == 3) ipuf = 4;  /* TET4 */
    if (elem[type][num_etype[type]].type == 4) ipuf = 26; /* HEX20 */
    if (elem[type][num_etype[type]].type == 5) ipuf = 20; /* PENTA15 */
    if (elem[type][num_etype[type]].type == 6) ipuf = 10; /* TET10 */
    if (elem[type][num_etype[type]].type == 7) ipuf = 3;  /* TRI3  */
    if (elem[type][num_etype[type]].type == 8) ipuf = 6;  /* TRI6  */
    if (elem[type][num_etype[type]].type == 9) ipuf = 4;  /* QUAD4 */
    if (elem[type][num_etype[type]].type == 10) ipuf = 8; /* QUAD8 */
    if (elem[type][num_etype[type]].type == 11) ipuf = 2; /* BEAM */
    if (elem[type][num_etype[type]].type == 12) ipuf = 3; /* BEAM3 */
    if (ipuf!=0)
    {
      for (n=0; n<ipuf; n++)
      {
        elem[type][num_etype[type]].nod[n]= e_enqire[ e_enqire[i].nr ].nod[n];
      }
    }
    num_etype[type]++;

    if(type>6) /* shell and beams */ 
    {
      if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+2) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
      face[anz->f].elem_nr= e_enqire[i].nr ;
      face[anz->f].group  = e_enqire[ e_enqire[i].nr ].group ;
      face[anz->f].type   = type;
      face[anz->f].mat    = 0 ; 
      face[anz->f].nr     = -1;
      face[anz->f].side   = NULL;
      for(j=0;j<ipuf;j++) face[anz->f].nod[j]= e_enqire[ e_enqire[i].nr ].nod[j] ;
      if(type==10) face[anz->f].nod[8]=e_enqire[e_enqire[i].nr].nod[8];
      anz->f++;
    }
  }

  if ( num_etype[1] > 0 )
  {
    numFaces = selectDisplayFacesHe8 ( elem[1], num_etype[1], &pfaces, &anz->g);

    if ( (edge = (Edges *)realloc( (Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n") ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces; i++)
    {
      face[i].nod[0]= *(pfacesN++) ;
      face[i].nod[1]= *(pfacesN++) ;
      face[i].nod[2]= *(pfacesN++) ;
      face[i].nod[3]= *(pfacesN++) ;
      face[i].elem_nr= *(pfacesN++) ;
      face[i].group  = *(pfacesN++) ;
      face[i].type   = 9 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
    }
    for (i=0; i<anz->g; i++)
    {
      edge[i].p1= *(pfacesN++) ;
      edge[i].p2= *(pfacesN++) ;
    }

    anz->f+=numFaces;

    free(pfaces);
  }

  if ( num_etype[2] > 0 )
  {
    ne=anz->g;
    numFaces = selectDisplayFacesPe6 ( elem[2], num_etype[2], &pfaces, &anz->g);

    anz->g+= ne;
    if ( (edge = (Edges *)realloc( (Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n") ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces; i++)
    {
      face[i].nod[0]= *(pfacesN++) ;
      face[i].nod[1]= *(pfacesN++) ;
      face[i].nod[2]= *(pfacesN++) ;
      face[i].nod[3]= *(pfacesN++) ;
      face[i].elem_nr= *(pfacesN++) ;
      face[i].group  = *(pfacesN++) ;
      face[i].type   = 9 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
    }
    for (i=ne; i<anz->g; i++)
    {
      edge[i].p1= *(pfacesN++) ;
      edge[i].p2= *(pfacesN++) ;
    }

    anz->f+=numFaces;

    free(pfaces);
  }

  if ( num_etype[3] > 0 )
  {
    ne=anz->g;
    numFaces = selectDisplayFacesTet4 ( elem[3], num_etype[3], &pfaces, &anz->g);
    anz->g+= ne;

    if ( (edge = (Edges *)realloc( (Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n") ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces; i++)
    {
      face[i].nod[0]= *(pfacesN++) ;
      face[i].nod[1]= *(pfacesN++) ;
      face[i].nod[2]= *(pfacesN++) ;pfacesN++;
      face[i].elem_nr= *(pfacesN++) ;
      face[i].group  = *(pfacesN++) ;
      face[i].type   = 7 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
    }
    for (i=ne; i<anz->g; i++)
    {
      edge[i].p1= *pfacesN++ ;
      edge[i].p2= *(pfacesN++) ;
    }
    anz->f+=numFaces;

    free(pfaces);
  }

  if ( num_etype[4] > 0 )
  {
    ne=anz->g;
    numFaces = selectDisplayFacesHe20( elem[4], num_etype[4], &pfaces, &anz->g); 

    anz->g+= ne;
    if ( (edge = (Edges *)realloc((Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n" ) ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces/8+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces/8; i++)
    {
      face[i].nod[0]= *(pfacesN    ) ;
      face[i].nod[1]= *(pfacesN+13 ) ;
      face[i].nod[2]= *(pfacesN+22 ) ;
      face[i].nod[3]= *(pfacesN+8  ) ;
      face[i].nod[4]= *(pfacesN+1  ) ;
      face[i].nod[5]= *(pfacesN+16 ) ;
      face[i].nod[6]= *(pfacesN+10 ) ;
      face[i].nod[7]= *(pfacesN+2  ) ;
      face[i].nod[8]= *(pfacesN+4  ) ;
      face[i].elem_nr= *(pfacesN+24) ;
      face[i].group  = *(pfacesN+25) ;
      face[i].type   = 10 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
      pfacesN+=26;
    }
    for (i=ne; i<anz->g; i+=2)
    {
      edge[i].p1= *pfacesN ;
      edge[i].p2= *(pfacesN+1) ;
      edge[i+1].p1= *(pfacesN+1) ;
      edge[i+1].p2= *(pfacesN+2) ;
      pfacesN+= 3;
    }
    anz->f+=numFaces/8;

    free(pfaces);
  }

  if ( num_etype[5] > 0 )
  {
    ne=anz->g;
    numFaces = selectDisplayFacesPe20 ( elem[5], num_etype[5], &pfaces, &anz->g); 

    anz->g+= ne;
    if ( (edge = (Edges *)realloc((Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n" ) ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces/8+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces/8; i++)
    {
      face[i].nod[0]= *(pfacesN    ) ;
      face[i].nod[1]= *(pfacesN+13 ) ;
      face[i].nod[2]= *(pfacesN+22 ) ;
      face[i].nod[3]= *(pfacesN+8  ) ;
      face[i].nod[4]= *(pfacesN+1  ) ;
      face[i].nod[5]= *(pfacesN+16 ) ;
      face[i].nod[6]= *(pfacesN+10 ) ;
      face[i].nod[7]= *(pfacesN+2  ) ;
      face[i].nod[8]= *(pfacesN+4  ) ;
      face[i].elem_nr= *(pfacesN+24) ;
      face[i].group  = *(pfacesN+25) ;
      face[i].type   = 10 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
      pfacesN+=26;
    }
    for (i=ne; i<anz->g; i+=2)
    {
      edge[i].p1= *pfacesN ;
      edge[i].p2= *(pfacesN+1) ;
      edge[i+1].p1= *(pfacesN+1) ;
      edge[i+1].p2= *(pfacesN+2) ;
      pfacesN+= 3;
    }
    anz->f+=numFaces/8;

    free(pfaces);
  }
  
  if ( num_etype[6] > 0 )
  {
    ne=anz->g;
    numFaces= selectDisplayFacesTet10 ( elem[6], num_etype[6], &pfaces, &anz->g);
    anz->g+= ne;

    if ( (edge = (Edges *)realloc((Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n" ) ;

    /* define the faces */
    if ( (face = (Faces *)realloc( (Faces *)face, (anz->f+numFaces/4+1) * sizeof(Faces))) == NULL )
      printf("\n\n ERROR: realloc failed surf3\n\n") ;
    pfacesN = pfaces;
    for (i=anz->f; i<anz->f+numFaces/4; i++)
    {
      face[i].nod[0]= *(pfacesN    ) ;
      face[i].nod[1]= *(pfacesN+12 ) ;
      face[i].nod[2]= *(pfacesN+17 ) ;
      face[i].nod[3]= *(pfacesN+6  ) ;
      face[i].nod[4]= *(pfacesN+16 ) ;
      face[i].nod[5]= *(pfacesN+15 ) ;
      face[i].elem_nr= *(pfacesN+18) ;
      face[i].group  = *(pfacesN+19) ;
      face[i].type   = 8 ;
      face[i].mat    = 0 ; 
      face[i].nr     = getFaceNr(face[i].elem_nr, face[i].nod);
      face[i].side   = NULL;
      pfacesN+=20;
    }
    for (i=ne; i<anz->g; i+=2)
    {
      edge[i].p1= *(pfacesN++) ;
      edge[i].p2= *(pfacesN) ;
      edge[i+1].p1= *(pfacesN++) ;
      edge[i+1].p2= *(pfacesN++) ;
    }
    anz->f+=numFaces/4;

    free(pfaces);
  }

  if ( num_etype[7] > 0 )
  {
    ns=anz->g;
    anz->g+=findCTri3Edges( elem[7], num_etype[7], &pfaces);
    pfacesN = pfaces;
 
    if ( (edge = (Edges *)realloc((Edges *)edge, (anz->g+1) * sizeof(Edges))) == NULL )
      printf("\n\n ERROR: realloc failed edge\n\n" ) ;
    for (i=ns; i<anz->g; i++)
    {
      edge[i].p1= *(pfacesN++) ;
      edge[i].p2= *(pfacesN) ;
      pfacesN+=4;
    }
    free(pfaces);
  }

  for(i=0; i<anz->f; i++)
  {
    if (face[i].type == 7)       nf=1;  /* TRI3  */
    else if (face[i].type == 8)  nf=4; /* TRI6  */
    else if (face[i].type == 9)  nf=2; /* QUAD4 */
    else if (face[i].type == 10) nf=8; /* QUAD8 */
    else if (face[i].type == 11) nf=1; /* BEAM */
    else if (face[i].type == 12) nf=1; /* BEAM3 */
    if((face[i].side=(double **)malloc((nf+1)*sizeof(double *)))==NULL)
    printf("\n\n ERROR: malloc failed\n\n" );
    for(k=0; k<nf; k++)
    {
      if((face[i].side[k]=(double *)malloc((3)*sizeof(double)))==NULL)
        printf("\n\n ERROR: malloc failed\n\n" );
    }
  }

  for (i=0; i<13; i++) { free(elem[i]); } 
  setall=getSetNr("all");
  if(setall>=0)
  {
    if((set[setall].face =(int *)realloc((int *)set[setall].face,(anz->f+1)*sizeof(int))) == NULL)
      printf(" ERROR: malloc failed in set[%d]:%s\n\n", setall, set[setall].name);
    set[setall].anz_f=anz->f;
    for (i=0; i<set[setall].anz_f; i++) set[setall].face[i]=i;
  }
  /* ini for elem-edges */
  getFaceNormalen( face, node, anz->f );
}


void iniMeshData( unsigned char *datin, unsigned char *format )
{
  int i;
  static clock_t t0, t1 ;
  int ***facebuf=NULL;
  Elements *elem=NULL;

  t0=clock() ;
  if(compare(format,"frd",3)==3)
  { 
    printf (" Try to read ccx results\n\n");
    if ( (readfrd( datin, anz, &node, &elem, &lcase)) == -1) { exit(-1);}
  }
  else if(compare(format,"ccx",3)==3)
  { 
    printf (" Try to read ccx input\n\n");
    anz->n=0;
    anz->e=0;
    anz->f=0;
    anz->g=0;
    anz->l=0;
    anz->emax=0;  anz->emin=MAXVALUE;
    anz->nmax=0;  anz->nmin=MAXVALUE;
    if ( (readccx( datin, anz, &node, &elem, &lcase, &facebuf)) == -1) { exit(-1);}
  }
  else if(compare(format,"isaac2d",7)==7)
  { 
    printf (" Try to read 2D-isaac results\n\n");
    if ( (  readIsaac( datin, anz, &node, &elem, &lcase, &nBlock, 9, pref, tref, R_GAS)) == -1) { exit(-1);}
  }
  else if(compare(format,"isaac3d",7)==7)
  { 
    printf (" Try to read 3D-isaac results\n\n");
    if ( (  readIsaac( datin, anz, &node, &elem, &lcase, &nBlock, 1, pref, tref, R_GAS)) == -1) { exit(-1);}
  }
  else if(compare(format,"duns2d",6)==6)
  { 
    printf (" Try to read 2D-duns results\n\n");
    if ( (  readDuns( datin, anz, &node, &elem, &lcase, 9)) == -1) { exit(-1);}
  }
  else if(compare(format,"duns3d",6)==6)
  { 
    printf (" Try to read 3D-duns results\n\n");
    if ( (  readDuns( datin, anz, &node, &elem, &lcase, 1)) == -1) { exit(-1);}
  }
  else if(compare(format,"foam",4)==4)
  { 
    printf (" Try to read foam results\n\n");
    if ( (  readFoam( datin, anz, &node, &elem, &lcase, &facebuf)) == -1) { exit(-1);}
  }
  else if(compare(format,"stl",3)==3)
  { 
    printf (" Try to read stl file\n\n");
    if ( (  readStl( datin, anz, &node, &elem, &lcase)) == -1) { exit(-1);}
  }
  t1=clock() ;
  printf (" Elements: %d Nodes:%d Datasets:%d ",anz->e,anz->n,anz->l);
  printf (" MinElemNr: %d MaxElemNr: %d MinNodNr:%d MaxNodNr:%d ",anz->emin,anz->emax,anz->nmin,anz->nmax);
  printf (" read in %lf sec \n",(double)(t1-t0)/CLOCKS_PER_SEC);
  for( i=1; i<13; i++) 
  {
    printf(" found elements of type %d: %d\n", i, anz->etype[i]);
  }

  iniElements(anz, elem, facebuf, 0);
  free(elem); elem=NULL;
}



void iniElements(Summen *anz, Elements *elem, int ***facebuf, int ini_e_enqire)
{
  int  i,k, n, n1, n2, setNr, ipuf, nf=0;

  /* flag the nodes */
  for( i=0; i<anz->n; i++) node[node[i].nr].pflag=0;

  num_onodmax   = anz->nmax;
  num_onod      = anz->n;
  num_olc       = anz->l;


  /* ------------- fill the element struktures -------------------------------- */

  /* free the e_enqire-structure */
  for (i=0; i<ini_e_enqire; i++ )
  {
    if(e_enqire[e_enqire[i].nr].side!=NULL)
    {
      /* free space for the normal-vectors */
      nf=0;
      if (e_enqire[e_enqire[i].nr].type == 1)       nf=6;  /* HEXA8 */
      else if (e_enqire[e_enqire[i].nr].type == 2)  nf=6;  /* PENTA6 */
      else if (e_enqire[e_enqire[i].nr].type == 3)  nf=4;  /* TET4 */
      else if (e_enqire[e_enqire[i].nr].type == 4)  nf=48; /* HEXA20 */
      else if (e_enqire[e_enqire[i].nr].type == 5)  nf=48; /* PENTA15 */
      else if (e_enqire[e_enqire[i].nr].type == 6)  nf=16; /* TET10 */
      else if (e_enqire[e_enqire[i].nr].type == 7)  nf=1;  /* TRI3  */
      else if (e_enqire[e_enqire[i].nr].type == 8)  nf=4; /* TRI6  */
      else if (e_enqire[e_enqire[i].nr].type == 9)  nf=2; /* QUAD4 */
      else if (e_enqire[e_enqire[i].nr].type == 10) nf=8; /* QUAD8 */
      else if (e_enqire[e_enqire[i].nr].type == 11) nf=1; /* BEAM */
      else if (e_enqire[e_enqire[i].nr].type == 12) nf=1; /* BEAM3 */
      if(nf)
      {
        for(k=0; k<nf; k++) free(e_enqire[e_enqire[i].nr].side[k]);
        free(e_enqire[e_enqire[i].nr].side);
        e_enqire[e_enqire[i].nr].side=NULL;
      }
    }
  }

  /* e_enqire is used as e_enqire[elem[i].nr].xx   */
  if ( (e_enqire = (Elements *)realloc((Elements *)e_enqire, (anz->emax+1) * sizeof(Elements))) == NULL )
    printf(" ERROR: realloc in iniMeshData(), e_enqire\n\n") ;
  for (i=0; i<anz->e; i++)
  {
    e_enqire[i].nr    = elem[i].nr;
    e_enqire[ elem[i].nr ].elem_nr    = i;
    e_enqire[ elem[i].nr ].group = elem[i].group;
    e_enqire[ elem[i].nr ].mat   = elem[i].mat;
    e_enqire[ elem[i].nr ].type  = elem[i].type;
    e_enqire[ elem[i].nr ].attr  = elem[i].attr;
    e_enqire[ elem[i].nr ].side  = NULL;


    if (elem[i].mat != elemMat[elemMat[0]])
    {
      for (n=1; n<elemMat[0]; n++) if (elem[i].mat == elemMat[n]) goto have_mat;
      elemMat[0]++; elemMat[elemMat[0]]=elem[i].mat;
      have_mat:;
    }
    ipuf=0;
    if (elem[i].type == 1) ipuf = 8;  /* HEXA8 */
    if (elem[i].type == 2) ipuf = 6;  /* PENTA6 */
    if (elem[i].type == 3) ipuf = 4;  /* TET4 */
    if (elem[i].type == 4) ipuf = 20; /* HEX20 */
    if (elem[i].type == 5) ipuf = 15; /* PENTA15 */
    if (elem[i].type == 6) ipuf = 10; /* TET10 */
    if (elem[i].type == 7) ipuf = 3;  /* TRI3  */
    if (elem[i].type == 8) ipuf = 6;  /* TRI6  */
    if (elem[i].type == 9) ipuf = 4;  /* QUAD4 */
    if (elem[i].type == 10) ipuf = 8; /* QUAD8 */
    if (elem[i].type == 11) ipuf = 2; /* BEAM */
    if (elem[i].type == 12) ipuf = 3; /* BEAM3 */
    if (ipuf!=0)
    {
      for (n=0; n<ipuf; n++)
      {
        e_enqire[ elem[i].nr ].nod[n]=elem[i].nod[n];
      }
    }
    if (elem[i].type == 4)
    {
      if ( (node = (Nodes *)realloc( (Nodes *)node, (anz->nmax+7) * sizeof(Nodes))) == NULL )
        printf("\n\n ERROR: realloc failed node\n\n") ;
      for (n=0; n<3; n++)  
      {
        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[0+n]].nx+node[elem[i].nod[1+n]].nx    +
          node[elem[i].nod[5+n]].nx+node[elem[i].nod[4+n]].nx )  + 1./2.*(
          node[elem[i].nod[8+n]].nx+node[elem[i].nod[13+n]].nx   +
          node[elem[i].nod[16+n]].nx+node[elem[i].nod[12+n]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[0+n]].ny+node[elem[i].nod[1+n]].ny    +
          node[elem[i].nod[5+n]].ny+node[elem[i].nod[4+n]].ny )  + 1./2.*(
          node[elem[i].nod[8+n]].ny+node[elem[i].nod[13+n]].ny   +
          node[elem[i].nod[16+n]].ny+node[elem[i].nod[12+n]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[0+n]].nz+node[elem[i].nod[1+n]].nz    +
          node[elem[i].nod[5+n]].nz+node[elem[i].nod[4+n]].nz )  + 1./2.*(
          node[elem[i].nod[8+n]].nz+node[elem[i].nod[13+n]].nz   +
          node[elem[i].nod[16+n]].nz+node[elem[i].nod[12+n]].nz) ;

        e_enqire[ elem[i].nr ].nod[n+20]=node[anz->n].nr;
        anz->n++;
      }
        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[3]].nx+node[elem[i].nod[0]].nx    +
          node[elem[i].nod[4]].nx+node[elem[i].nod[7]].nx )  + 1./2.*(
          node[elem[i].nod[11]].nx+node[elem[i].nod[12]].nx   +
          node[elem[i].nod[19]].nx+node[elem[i].nod[15]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[3]].ny+node[elem[i].nod[0]].ny    +
          node[elem[i].nod[4]].ny+node[elem[i].nod[7]].ny )  + 1./2.*(
          node[elem[i].nod[11]].ny+node[elem[i].nod[12]].ny   +
          node[elem[i].nod[19]].ny+node[elem[i].nod[15]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[3]].nz+node[elem[i].nod[0]].nz    +
          node[elem[i].nod[4]].nz+node[elem[i].nod[7]].nz )  + 1./2.*(
          node[elem[i].nod[11]].nz+node[elem[i].nod[12]].nz   +
          node[elem[i].nod[19]].nz+node[elem[i].nod[15]].nz) ;

        e_enqire[ elem[i].nr ].nod[23]=node[anz->n].nr;
        anz->n++;

      for (n=0; n<2; n++) 
      {
        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        n1=n*4;
        n2=n*8;
        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[0+n1]].nx+node[elem[i].nod[1+n1]].nx    +
          node[elem[i].nod[2+n1]].nx+node[elem[i].nod[3+n1]].nx )  + 1./2.*(
          node[elem[i].nod[8+n2]].nx+node[elem[i].nod[9+n2]].nx   +
          node[elem[i].nod[10+n2]].nx+node[elem[i].nod[11+n2]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[0+n1]].ny+node[elem[i].nod[1+n1]].ny    +
          node[elem[i].nod[2+n1]].ny+node[elem[i].nod[3+n1]].ny )  + 1./2.*(
          node[elem[i].nod[8+n2]].ny+node[elem[i].nod[9+n2]].ny   +
          node[elem[i].nod[10+n2]].ny+node[elem[i].nod[11+n2]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[0+n1]].nz+node[elem[i].nod[1+n1]].nz    +
          node[elem[i].nod[2+n1]].nz+node[elem[i].nod[3+n1]].nz )  + 1./2.*(
          node[elem[i].nod[8+n2]].nz+node[elem[i].nod[9+n2]].nz   +
          node[elem[i].nod[10+n2]].nz+node[elem[i].nod[11+n2]].nz) ;

        e_enqire[ elem[i].nr ].nod[n+24]=node[anz->n].nr;
        anz->n++;
      }
    }
    if (elem[i].type == 5)
    {
      if ( (node = (Nodes *)realloc( (Nodes *)node, (anz->nmax+6) * sizeof(Nodes))) == NULL )
        printf("\n\n ERROR: realloc failed node\n\n") ;
      for (n=0; n<2; n++)  
      {
        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[0+n]].nx+node[elem[i].nod[1+n]].nx    +
          node[elem[i].nod[4+n]].nx+node[elem[i].nod[3+n]].nx )  + 1./2.*(
          node[elem[i].nod[6+n]].nx+node[elem[i].nod[10+n]].nx   +
          node[elem[i].nod[12+n]].nx+node[elem[i].nod[ 9+n]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[0+n]].ny+node[elem[i].nod[1+n]].ny    +
          node[elem[i].nod[4+n]].ny+node[elem[i].nod[3+n]].ny )  + 1./2.*(
          node[elem[i].nod[6+n]].ny+node[elem[i].nod[10+n]].ny   +
          node[elem[i].nod[12+n]].ny+node[elem[i].nod[ 9+n]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[0+n]].nz+node[elem[i].nod[1+n]].nz    +
          node[elem[i].nod[4+n]].nz+node[elem[i].nod[3+n]].nz )  + 1./2.*(
          node[elem[i].nod[6+n]].nz+node[elem[i].nod[10+n]].nz   +
          node[elem[i].nod[12+n]].nz+node[elem[i].nod[ 9+n]].nz) ;

        e_enqire[ elem[i].nr ].nod[n+15]=node[anz->n].nr;
        anz->n++;
      }
        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[2]].nx+node[elem[i].nod[0]].nx    +
          node[elem[i].nod[3]].nx+node[elem[i].nod[5]].nx )  + 1./2.*(
          node[elem[i].nod[ 8]].nx+node[elem[i].nod[ 9]].nx   +
          node[elem[i].nod[14]].nx+node[elem[i].nod[11]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[2]].ny+node[elem[i].nod[0]].ny    +
          node[elem[i].nod[3]].ny+node[elem[i].nod[5]].ny )  + 1./2.*(
          node[elem[i].nod[ 8]].ny+node[elem[i].nod[ 9]].ny   +
          node[elem[i].nod[14]].ny+node[elem[i].nod[11]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[2]].nz+node[elem[i].nod[0]].nz    +
          node[elem[i].nod[3]].nz+node[elem[i].nod[5]].nz )  + 1./2.*(
          node[elem[i].nod[ 8]].nz+node[elem[i].nod[ 9]].nz   +
          node[elem[i].nod[14]].nz+node[elem[i].nod[11]].nz) ;

        e_enqire[ elem[i].nr ].nod[17]=node[anz->n].nr;
        anz->n++;

        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[0]].nx+node[elem[i].nod[2]].nx    +
          node[elem[i].nod[1]].nx+node[elem[i].nod[0]].nx )  + 1./2.*(
          node[elem[i].nod[ 8]].nx+node[elem[i].nod[ 7]].nx   +
          node[elem[i].nod[ 6]].nx+node[elem[i].nod[ 0]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[0]].ny+node[elem[i].nod[2]].ny    +
          node[elem[i].nod[1]].ny+node[elem[i].nod[0]].ny )  + 1./2.*(
          node[elem[i].nod[ 8]].ny+node[elem[i].nod[ 7]].ny   +
          node[elem[i].nod[ 6]].ny+node[elem[i].nod[ 0]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[0]].nz+node[elem[i].nod[2]].nz    +
          node[elem[i].nod[1]].nz+node[elem[i].nod[0]].nz )  + 1./2.*(
          node[elem[i].nod[ 8]].nz+node[elem[i].nod[ 7]].nz   +
          node[elem[i].nod[ 6]].nz+node[elem[i].nod[ 0]].nz) ;

        e_enqire[ elem[i].nr ].nod[18]=node[anz->n].nr;
        anz->n++;

        anz->nmax++;
        node[anz->n].nr = anz->nmax;
        node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[elem[i].nod[3]].nx+node[elem[i].nod[4]].nx    +
          node[elem[i].nod[5]].nx+node[elem[i].nod[3]].nx )  + 1./2.*(
          node[elem[i].nod[12]].nx+node[elem[i].nod[13]].nx   +
          node[elem[i].nod[14]].nx+node[elem[i].nod[ 3]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[elem[i].nod[3]].ny+node[elem[i].nod[4]].ny    +
          node[elem[i].nod[5]].ny+node[elem[i].nod[3]].ny )  + 1./2.*(
          node[elem[i].nod[12]].ny+node[elem[i].nod[13]].ny   +
          node[elem[i].nod[14]].ny+node[elem[i].nod[ 3]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[elem[i].nod[3]].nz+node[elem[i].nod[4]].nz    +
          node[elem[i].nod[5]].nz+node[elem[i].nod[3]].nz )  + 1./2.*(
          node[elem[i].nod[12]].nz+node[elem[i].nod[13]].nz   +
          node[elem[i].nod[14]].nz+node[elem[i].nod[ 3]].nz) ;

        e_enqire[ elem[i].nr ].nod[19]=node[anz->n].nr;
        anz->n++;
    }
    if (elem[i].type == 10)
    {
      /* calculate the midside node */
      if ( (node = (Nodes *)realloc( (Nodes *)node, (anz->nmax+2) * sizeof(Nodes))) == NULL )
        printf("\n\n ERROR: realloc failed node\n\n") ;
      anz->nmax++;
      node[anz->n].nr = anz->nmax;
      node[anz->nmax].pflag=1;

        node[anz->nmax].nx = -1./4.* (
          node[e_enqire[e_enqire[i].nr].nod[0]].nx+node[e_enqire[e_enqire[i].nr].nod[1]].nx  +
          node[e_enqire[e_enqire[i].nr].nod[3]].nx+node[e_enqire[e_enqire[i].nr].nod[2]].nx )+ 1./2.*(
          node[e_enqire[e_enqire[i].nr].nod[4]].nx+node[e_enqire[e_enqire[i].nr].nod[6]].nx  +
          node[e_enqire[e_enqire[i].nr].nod[7]].nx+node[e_enqire[e_enqire[i].nr].nod[5]].nx) ;

        node[anz->nmax].ny = -1./4.* (
          node[e_enqire[e_enqire[i].nr].nod[0]].ny+node[e_enqire[e_enqire[i].nr].nod[1]].ny  +
          node[e_enqire[e_enqire[i].nr].nod[3]].ny+node[e_enqire[e_enqire[i].nr].nod[2]].ny )+ 1./2.*(
          node[e_enqire[e_enqire[i].nr].nod[4]].ny+node[e_enqire[e_enqire[i].nr].nod[6]].ny  +
          node[e_enqire[e_enqire[i].nr].nod[7]].ny+node[e_enqire[e_enqire[i].nr].nod[5]].ny) ;

        node[anz->nmax].nz = -1./4.* (
          node[e_enqire[e_enqire[i].nr].nod[0]].nz+node[e_enqire[e_enqire[i].nr].nod[1]].nz  +
          node[e_enqire[e_enqire[i].nr].nod[3]].nz+node[e_enqire[e_enqire[i].nr].nod[2]].nz )+ 1./2.*(
          node[e_enqire[e_enqire[i].nr].nod[4]].nz+node[e_enqire[e_enqire[i].nr].nod[6]].nz  +
          node[e_enqire[e_enqire[i].nr].nod[7]].nz+node[e_enqire[e_enqire[i].nr].nod[5]].nz) ;
        e_enqire[e_enqire[i].nr].nod[8]=node[anz->n].nr;
        anz->n++;
    }

  }

  for (i=0; i<anz->e; i++ )
  {
    /* space for the normal-vectors */
    if (e_enqire[e_enqire[i].nr].type == 1)       nf=6;  /* HEXA8 */
    else if (e_enqire[e_enqire[i].nr].type == 2)  nf=6;  /* PENTA6 */
    else if (e_enqire[e_enqire[i].nr].type == 3)  nf=4;  /* TET4 */
    else if (e_enqire[e_enqire[i].nr].type == 4)  nf=48; /* HEXA20 */
    else if (e_enqire[e_enqire[i].nr].type == 5)  nf=48; /* PENTA15 */
    else if (e_enqire[e_enqire[i].nr].type == 6)  nf=16; /* TET10 */
    else if (e_enqire[e_enqire[i].nr].type == 7)  nf=1;  /* TRI3  */
    else if (e_enqire[e_enqire[i].nr].type == 8)  nf=4; /* TRI6  */
    else if (e_enqire[e_enqire[i].nr].type == 9)  nf=2; /* QUAD4 */
    else if (e_enqire[e_enqire[i].nr].type == 10) nf=8; /* QUAD8 */
    else if (e_enqire[e_enqire[i].nr].type == 11) nf=1; /* BEAM */
    else if (e_enqire[e_enqire[i].nr].type == 12) nf=1; /* BEAM3 */

    if((e_enqire[e_enqire[i].nr].side=(double **)malloc((nf)*sizeof(double *)))==NULL)
      printf("\n\n ERROR: malloc failed\n\n" );
    for(k=0; k<nf; k++)
    {
      if((e_enqire[e_enqire[i].nr].side[k]=(double *)malloc((3)*sizeof(double)))==NULL)
        printf("\n\n ERROR: malloc failed\n\n" );
    }
  }

  getElemNormalen( e_enqire, node, anz->e );
  makeSurfaces();

  /* if an ccx input was read then the faces created in makeSurfaces() must be assigned to the sets */
  /* the faces were stored in facebuf */
  /* go through all sets and see if faces are stored */
  if(facebuf!=NULL)
  {
    for(n=facebuf[0][0][0]; n>=0; n--)
    {
      setNr=facebuf[n][0][1];
      /* store the face indexes in the set */
      setall=getSetNr("all");
      if(setall>=0)
      {
        for(i=0; i<set[setall].anz_f; i++)
        {
          n2=face[i].nr;
          n1=face[i].elem_nr;
          /*  printf("facebuf seta %s %d f:%d e:%d  facebuf[n][n1][n2]:%d\n",set[setNr].name, i, n2, n1, facebuf[n][n1][n2]); */
          if(facebuf[n][n1][n2]==1)
          {
            seta( setNr, "f", i);
	  }
        }
      }
    
      /* free facebuf[n] */
      for(i=0; i<anz->emax+1; i++) free(facebuf[n][i]); free(facebuf[n]); 
    }
    free(facebuf);
  }

  allocUtilityData();
}

