/* --------------------------------------------------------------------  */
/*                          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.         */
/* --------------------------------------------------------------------  */

/* BUGS
 search for "bug:"
 */

#include <cgx.h>
#define TEST 0
#define NASMPC   0      /* MPCs: 1 RBEs: 0 */




extern int       neqn;                 /* offset der equations fuer ansys, bzw. MPC ID fuer Nast. */

extern int   offset, maxIndex;                            /* offset+steps-1 = maxIndex */
extern int   basCol[3];                     /* color indexes due to basic colormap */
extern int   width_ini, height_ini; /* Grafig-Fensterbreite/hoehe */
extern int   width_menu, height_menu;
extern int   w0, w1, w_index, w_rgb, activWindow;
extern int   width_w0, height_w0;
extern int   width_w1, height_w1;
extern int   MouseMode;                                   /* status maustasten */
extern double dtx, dty, dtz, drx, dry, drz, ds;                 /* Verschiebungen */
extern double vmem[4];                                     /* kor. bis auswahl eines neuen drehpkts */
extern GLdouble R[4][4];                                   /* Rotationsmatrix */
extern unsigned char  surfFlag;                /* zeichne nur Oberflaechenelemente (1), sonst (0)*/
extern unsigned char  modelEdgeFlag;                /* zeichne mit Modell-Ecken (1), sonst (0)*/
extern unsigned char  frameFlag;                   /* mit (1) oder ohne Rahmen um das Grafikfenster */
extern unsigned char  filenamFlag;                   /* mit (1) oder ohne filename im Menufenster */
extern unsigned char  textFlag;                   /* mit (1) oder ohne text im Menufenster */
extern unsigned char  printFlag;                     /* printf 1:on 0:off */
extern unsigned char  cullFlag;                     /* (1) enable Culling */
extern unsigned char  frameFlag;               /* mit (1) oder ohne Rahmen um das Grafigfenster */
extern unsigned char  scalaFlag;                 /* mit (1) oder ohne scala und wertetexte */ 
extern double dx ,dy;                                      /* Mauskoordinaten */
extern int   steps;                   /* Schrittweite der Farbscala, und NURB aufloesung */
extern double gtol;
extern unsigned char  picture_text[MAX_LINE_LENGTH], datin[MAX_LINE_LENGTH];

extern unsigned char  delPntFlag;                    /* 1: deleted points exists */
extern unsigned char  delLineFlag;                   /* 1: deleted lines exists */
extern unsigned char  delLcmbFlag;                   /* 1: deleted lcmbs exists */
extern unsigned char  delSurfFlag;                   /* 1: deleted surfs exists */
extern unsigned char  delBodyFlag;                   /* 1: deleted bodys exists */

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 Scale     scale[1];
extern double     *value_n;
extern Summen    anz[1];
extern Edges     *edge;
extern Nodes     *node;
extern Elements  *e_enqire;
extern Nodes     *n_anim;
extern Datasets *lcase;
extern Faces     *face;

extern Alias     *alias;
extern Sets      *set;
extern Psets     *pset;
extern Points    *point;
extern Lines     *line;
extern Lcmb      *lcmb;
extern Gsur      *surf;
extern Gbod      *body;
extern Nurbs     *nurbs;
extern SumGeo    anzGeo[1];
extern SumAsci   sumAsci[1];

extern int       num_olc;

extern SpecialSet specialset[1];

extern int       offset;


#define     DOFX        1
#define     DOFY        2
#define     DOFZ        3
#define     DOFT        11
#define     DPHI_TOL    0.017453      /* 1grd */

#define     N_CLOSEST_NODES 10

double   MIN_C={0.9};   /* zulaessiger flaechenfehler in calcCoefficients(), {0.9} */
double   MAX_C={1.1};   /* wird durch verschieben der nodes korrigiert       {1.1} */

void sendMpc( unsigned char *setname, unsigned char *format, Summen *anz, Nodes *node, Elements *e_enqire, unsigned char *rotation , double *vector)
{
  int   i,j;
  int   length, setNr;
  unsigned char prognam[MAX_LINE_LENGTH], boundary[MAX_LINE_LENGTH];

  FILE *handle, *handle_boundary;


  strcpy ( prognam, setname);
  length= strlen ( setname );
  setNr=getSetNr(setname);
  if (setNr<0)
  {
    printf (" ERROR: set:%s does not exist\n", setname);
    return;
  }

  strcpy ( prognam, setname);
  length= strlen ( setname );
  strcpy (&prognam[length], ".mpc");

  /* write the mpcs in abaqus-format */
  if (compare( format, "abq", 3)== 3)
  {
    handle = fopen (prognam, "w");
    if ( handle== NULL )
    {
      printf ("\nThe input file %s could not be opened.\n\n", prognam); 
      return;
    }

    strcpy ( boundary, setname);
    length= strlen ( setname );
    strcpy (&boundary[length], ".bou");
    handle_boundary = fopen (boundary, "w");
    if ( handle_boundary== NULL )
    {
      printf ("\nThe input file %s could not be opened.\n\n", boundary); 
      return;
    }

    fprintf(handle, "** INCLUDE THE FOLLOWING LINES IN THE MODEL-DEFINITION-SECTION:\n");
    fprintf(handle, "**   THE LOCATION OF THE INDEPENDENT NODE FOR PRETWIST\n");
    fprintf(handle, "**   IS USED TO DEFINE THE DIRECTION OF THE ROTATIONAL VECTOR\n");
    fprintf(handle, "**     AROUND X: 1.,0.,0.\n");
    fprintf(handle, "**     AROUND Y: 0.,1.,0.\n");
    fprintf(handle, "**     AROUND Z: 0.,0.,1. (DEFAULT)\n");
    fprintf(handle, "*NODE, NSET=Ntwist\n");
    fprintf(handle, "%d,%lf,%lf,%lf\n",num_onodmax+1,vector[0],vector[1],vector[2] );
    fprintf(handle, "*MPC, USER\n1,");
    j=0; for (i=0; i<set[setNr].anz_n; i++ )
    {
      if( j>12 )
      {
        j=0;
        fprintf(handle, "\n0,");
      }
      fprintf(handle, "%d,",set[setNr].node[i]);
      j++;
      fprintf(handle, "%d,",set[setNr].node[i]);
      j++;
      fprintf(handle, "%d,",set[setNr].node[i]);
      j++;
    }
    if(j>14) fprintf(handle, "\n0,%d\n", num_onodmax+1);
    else fprintf(handle, "%d\n", num_onodmax+1);
    fclose(handle);

    fprintf(handle_boundary, "**INCLUDE THE FOLLOWING LINES IN A STEP:\n");
    fprintf(handle_boundary, "**  Pretwist of %s degree\n*BOUNDARY\n", rotation);
    fprintf(handle_boundary, "%d, 1, 1, %lf\n", num_onodmax+1, atof(rotation)*PI/180.);
    fclose(handle_boundary);
  }
  else
  {
    errMsg(" ERROR: format %s not yet supported\n", format );
  }
  printf (" ready\n");
}


void cycmpc(int set1, int set2, unsigned char *format, unsigned char *value, unsigned char *corr)
{
  int i,j;
  int firstrun;
  unsigned char  datout[MAX_LINE_LENGTH], buffer[MAX_LINE_LENGTH];
  double dphi, phi_teilung, phi_vorgabe=0.;
  unsigned char  csys, axis;
  double *nx1=0, *nx2=0;
  double *nt1=0, *nt2=0;
  double *nr1=0, *nr2=0;
  double *phi=0;
  FILE  *handle;
  Nodes *node1=0;          /* dep nodes */
  Nodes *node2=0;          /* indep nodes */

  double rmin,dx,dr,R,f;
  int   node2j=0;


  if ( (compare( format, "abq", 3)!= 3)&&
       (compare( format, "ans", 3)!= 3)&&
       (compare( format, "nas", 3)!= 3) ) 
  {
    errMsg ("ERROR: format:%s not known\n\n", format);
    return;
  }

  /* ---- clear special sets ----- */
  delSet(specialset->mpc );
  delSet(specialset->nompc );


  /* Open the files and check to see that it was opened correctly */
  sprintf(datout, "%s.equ", set[set1].name);
  if(printFlag) printf ("datout:%s set1:%s nodes:%d set2:%s nodes:%d\n",datout, set[set1].name, set[set1].anz_n, set[set2].name, set[set2].anz_n);
  handle = fopen (datout, "w");
  if (handle==NULL) { printf ("\nThe output file \"%s\" could not be opened.\n\n", datout); return; }
  else  printf (" %s opened\n", datout);
  if (compare( format, "abq", 3)== 3)      fprintf(handle, "** cycmpc based on set %s %s\n",set[set1].name, set[set2].name );
  else if (compare( format, "ans", 3)== 3) fprintf(handle, "! cycmpc based on set %s %s\n",set[set1].name, set[set2].name );
  else if (compare( format, "nas", 3)== 3) fprintf(handle, "$ cycmpc based on set %s %s\n",set[set1].name, set[set2].name );

  csys=value[0];
  axis=value[1];
  i=atoi(&corr[1]);    /* startnummer der equations in abaqus, oder id in nastran */
  if(i>0) neqn=i-1;
  f=atof(&value[2]);
  if(f!=0.) phi_vorgabe=2.*PI /f;  /* teilungswinkel, berechnet aus der segmentzahl */


  /* ------- node-koordinaten berechnen und am ende wieder scalieren ------ */
  descalNodes ( anz->n, node, scale );


  /* --------- Seitenflaeche einlesen und Daten aufbereiten --------------- */

  if ( (node1 = (Nodes *)malloc( set[set1].anz_n * sizeof(Nodes))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (node2 = (Nodes *)malloc( set[set2].anz_n * sizeof(Nodes))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nx1 = (double *)malloc( set[set1].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nx2 = (double *)malloc( set[set2].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nt1 = (double *)malloc( set[set1].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nt2 = (double *)malloc( set[set2].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nr1 = (double *)malloc( set[set1].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (nr2 = (double *)malloc( set[set2].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }
  if ( (phi = (double *)malloc( set[set1].anz_n * sizeof(double))) == NULL )
  {
    errMsg("\nERROR: malloc failed in cycmpc() \n\n");
    goto end;
  }

  /* nodes zuweisen */
  for (i=0; i<set[set1].anz_n; i++ ) node1[i].nr=set[set1].node[i];  
  for (i=0; i<set[set2].anz_n; i++ ) node2[i].nr=set[set2].node[i];  


  /* --------- R,Theta,x Koordinaten berechnen  */

  if (set[set1].anz_n > anz->n) {printf(" ERROR: side has more nodes than the model"); exit(-1);}


 if(axis=='x')
 {
  if(printFlag) printf(" x-axis specified\n");
  for (i=0; i<set[set1].anz_n; i++ )
  {
    nx1[i]= node[node1[i].nr].nx;
    nr1[i]= sqrt( node[node1[i].nr].nz*node[node1[i].nr].nz + node[node1[i].nr].ny*node[node1[i].nr].ny );
    if ( nr1[i] )
    {
      nt1[i]= p_angle( node[node1[i].nr].nz, node[node1[i].nr].ny ); 
    }
  }
  for (i=0; i<set[set2].anz_n; i++ )
  {
    nx2[i]= node[node2[i].nr].nx;
    nr2[i]= sqrt( node[node2[i].nr].nz*node[node2[i].nr].nz + node[node2[i].nr].ny*node[node2[i].nr].ny );
    if ( nr2[i] )
    {
      nt2[i]= p_angle( node[node2[i].nr].nz, node[node2[i].nr].ny );
    }
  }



  /* suche nodepaare, berechne differenzwinkel und schreibe EQUATION's  */
  for (i=0; i<set[set1].anz_n; i++ )
  {
   if (nr1[i]>0)
   {
    /* suche gegenueber liegenden naechsten node  */
    rmin=MAXVALUE;
    for (j=0; j<set[set2].anz_n; j++ )
    {
      if ((nr2[j]>0)&&( node2[j].nr!= node1[i].nr))
      {
        dx= nx2[j]-nx1[i];
        dr= nr2[j]-nr1[i];
        R=sqrt( dx*dx + dr*dr );
        if (R<rmin)
        {
          rmin=R;
          node2j=j;
        }
      }
    }

    /* berechne den differenzwinkel  */
    phi[i]= nt2[node2j]-nt1[i];

    /* definiere den Zielwinkel, entweder vorgabe oder wie berechnet */
    if(phi_vorgabe==0.) phi_teilung=phi[i];
    else phi_teilung=phi_vorgabe;

    firstrun=1;
   nexttryx:;
    /* kontrolliere den differenzwinkel mit der teilung */
    dphi = phi_teilung - phi[i];
    if(dphi>2.*PI-DPHI_TOL) while (dphi>2.*PI-DPHI_TOL) dphi-=2.*PI;
    if(dphi<-2.*PI+DPHI_TOL) while (dphi<-2.*PI+DPHI_TOL) dphi+=2.*PI;
    if ((dphi*dphi > DPHI_TOL)&&(firstrun))
    {
      firstrun=0;
      phi_teilung=-phi_vorgabe;
      goto nexttryx;
    }
    else if ((dphi*dphi > DPHI_TOL)&&(!firstrun))
    {
      errMsg ("ERROR: korresponding node too far away:%lf grd, see set %s\n",dphi*180./PI, specialset->nompc);
      sprintf( buffer, "%d", node1[i].nr); 
      pre_seta(specialset->nompc, "n", buffer);
    }
    else 
    {
    if(printFlag) printf(" theta(%d):%lf theta(%d):%lf  dtheta:%lf dtheta_corr:%lf rmin:%lf\n",
      node1[i].nr, nt1[i]*180./PI, node2[node2j].nr, nt2[node2j]*180./PI,
      phi[i]*180./PI, phi_teilung*180./PI, rmin);

    if (corr[0]=='c')
    { 
      /* versetze den gefundenen Knoten auf die korrespondierende pos. */
      /* der dependent node wird auf die pos des indep gesetzt */
      node[node1[i].nr].nx = node[node2[node2j].nr].nx;
      if ( nr1[i] )
      {
        node[node1[i].nr].ny = node[node2[node2j].nr].ny*cos(phi_teilung)-node[node2[node2j].nr].nz*sin(phi_teilung);
        node[node1[i].nr].nz = node[node2[node2j].nr].ny*sin(phi_teilung)+node[node2[node2j].nr].nz*cos(phi_teilung);
      }  
    }


   if (csys=='t')
   {
    if (compare( format, "abq", 3)== 3)
    {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFT, 1.,
          node2[node2j].nr, DOFT, -1. );
    }
   }
   if (csys=='r')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -cos(phi_teilung),  node2[node2j].nr, DOFZ, sin(phi_teilung) );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFY, -sin(phi_teilung),  node2[node2j].nr, DOFZ, -cos(phi_teilung) );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UX", 1.,
              node1[i].nr, "UX", 1., node2[node2j].nr, "UX", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UY", 1.,
              node2[node2j].nr, "UY", -cos(phi_teilung), node2[node2j].nr, "UZ", sin(phi_teilung) );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UZ", 1.,
              node2[node2j].nr, "UY", -sin(phi_teilung), node2[node2j].nr, "UZ", -cos(phi_teilung) );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
                                                          node2[node2j].nr, DOFY, -cos(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFZ, sin(phi_teilung) );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
                                                          node2[node2j].nr, DOFY, -sin(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFZ, -cos(phi_teilung) );
      }
    }
   if (csys=='c')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UX", 1.,
              node1[i].nr, "UX", 1., node2[node2j].nr, "UX", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UY", 1.,
              node1[i].nr, "UY", 1., node2[node2j].nr, "UY", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UZ", 1.,
              node1[i].nr, "UZ", 1., node2[node2j].nr, "UZ", -1. );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    }
   sprintf( buffer, "%d", node1[i].nr); 
   pre_seta(specialset->mpc, "n", buffer);
   }
   }
  }
 }
 else if(axis=='y')
 {
  if(printFlag) printf("y-axis specified\n");
  for (i=0; i<set[set1].anz_n; i++ )
  {
    nx1[i]= node[node1[i].nr].ny;
    nr1[i]= sqrt( node[node1[i].nr].nz*node[node1[i].nr].nz + node[node1[i].nr].nx*node[node1[i].nr].nx );
    if ( nr1[i] )
    {
      nt1[i]= p_angle( node[node1[i].nr].nx, node[node1[i].nr].nz ); 
    }
  }
  for (i=0; i<set[set2].anz_n; i++ )
  {
    nx2[i]= node[node2[i].nr].ny;
    nr2[i]= sqrt( node[node2[i].nr].nz*node[node2[i].nr].nz + node[node2[i].nr].nx*node[node2[i].nr].nx );
    if ( nr2[i] )
    {
      nt2[i]= p_angle( node[node2[i].nr].nx, node[node2[i].nr].nz ); 
    }
  }



  /* suche nodepaare, berechne differenzwinkel und schreibe EQUATION's  */
  for (i=0; i<set[set1].anz_n; i++ )
  {
   if (nr1[i]>0)
   {
    /* suche gegenueber liegenden naechsten node  */
    rmin=MAXVALUE;
    for (j=0; j<set[set2].anz_n; j++ )
    {
      if ((nr2[j]>0)&&( node2[j].nr!= node1[i].nr))
      {
        dx= nx2[j]-nx1[i];
        dr= nr2[j]-nr1[i];
        R=sqrt( dx*dx + dr*dr );
        if (R<rmin)
        {
          rmin=R;
          node2j=j;
        }
      }
    }

    /* berechne den differenzwinkel  */
    phi[i]= nt2[node2j]-nt1[i];

    /* definiere den Zielwinkel, entweder vorgabe oder wie berechnet */
    if(phi_vorgabe==0.) phi_teilung=phi[i];
    else phi_teilung=phi_vorgabe;

    firstrun=1;
   nexttryy:;
    /* kontrolliere den differenzwinkel mit der teilung */
    dphi = phi_teilung - phi[i];
    if(dphi>2.*PI-DPHI_TOL) while (dphi>2.*PI-DPHI_TOL) dphi-=2.*PI;
    if(dphi<-2.*PI+DPHI_TOL) while (dphi<-2.*PI+DPHI_TOL) dphi+=2.*PI;
    if ((dphi*dphi > DPHI_TOL)&&(firstrun))
    {
      firstrun=0;
      phi_teilung=-phi_vorgabe;
      goto nexttryy;
    }
    else if ((dphi*dphi > DPHI_TOL)&&(!firstrun))
    {
      errMsg ("ERROR: korresponding node too far away:%lf grd, see set %s\n",dphi*180./PI, specialset->nompc);
      sprintf( buffer, "%d", node1[i].nr); 
      pre_seta(specialset->nompc, "n", buffer);
    }
    else 
    {

    if(printFlag) printf(" theta(%d):%lf theta(%d):%lf  dtheta:%lf dtheta_corr:%lf rmin:%lf\n",
      node1[i].nr, nt1[i]*180./PI, node2[node2j].nr, nt2[node2j]*180./PI,
      phi[i]*180./PI, phi_teilung*180./PI, rmin);

    if (corr[0]=='c')
    { 
      /* versetze den gefundenen Knoten auf die korrespondierende pos. */
      /* der dependent node wird auf die pos des indep gesetzt */
      node[node1[i].nr].ny = node[node2[node2j].nr].ny;
      if ( nr1[i] )
      {
        node[node1[i].nr].nx = node[node2[node2j].nr].nz*sin(phi_teilung) + node[node2[node2j].nr].nx*cos(phi_teilung);
        node[node1[i].nr].nz = node[node2[node2j].nr].nz*cos(phi_teilung) - node[node2[node2j].nr].nx*sin(phi_teilung);
      }  
    }  


   if (csys=='t')
   {
    if (compare( format, "abq", 3)== 3)
    {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFT, 1.,
          node2[node2j].nr, DOFT, -1. );
    }
   }
   if (csys=='r')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -cos(phi_teilung),  node2[node2j].nr, DOFX, sin(phi_teilung) );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFZ, -sin(phi_teilung),  node2[node2j].nr, DOFX, -cos(phi_teilung) );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UY", 1.,
              node1[i].nr, "UY", 1., node2[node2j].nr, "UY", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UZ", 1.,
              node2[node2j].nr, "UZ", -cos(phi_teilung), node2[node2j].nr, "UX", sin(phi_teilung) );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UX", 1.,
              node2[node2j].nr, "UZ", -sin(phi_teilung), node2[node2j].nr, "UX", -cos(phi_teilung) );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
                                                          node2[node2j].nr, DOFZ, -cos(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFX, sin(phi_teilung) );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
                                                          node2[node2j].nr, DOFZ, -sin(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFX, -cos(phi_teilung) );
      }
    }
   if (csys=='c')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UX", 1.,
              node1[i].nr, "UX", 1., node2[node2j].nr, "UX", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UY", 1.,
              node1[i].nr, "UY", 1., node2[node2j].nr, "UY", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UZ", 1.,
              node1[i].nr, "UZ", 1., node2[node2j].nr, "UZ", -1. );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    }
   sprintf( buffer, "%d", node1[i].nr); 
   pre_seta(specialset->mpc, "n", buffer);
   }
   }
  }
 }
 else if(axis=='z')
 {
  if(printFlag) printf("z-axis specified\n");
  for (i=0; i<set[set1].anz_n; i++ )
  {
    nx1[i]= node[node1[i].nr].nz;
    nr1[i]= sqrt( node[node1[i].nr].nx*node[node1[i].nr].nx + node[node1[i].nr].ny*node[node1[i].nr].ny );
    if ( nr1[i] )
    {
      nt1[i]= p_angle( node[node1[i].nr].ny, node[node1[i].nr].nx );
    }
  }
  for (i=0; i<set[set2].anz_n; i++ )
  {
    nx2[i]= node[node2[i].nr].nz;
    nr2[i]= sqrt( node[node2[i].nr].nx*node[node2[i].nr].nx + node[node2[i].nr].ny*node[node2[i].nr].ny );
    if ( nr2[i] )
    {
      nt2[i]= p_angle( node[node2[i].nr].ny, node[node2[i].nr].nx );
    }
  }



  /* suche nodepaare, berechne differenzwinkel und schreibe EQUATION's  */
  for (i=0; i<set[set1].anz_n; i++ )
  {
   if (nr1[i]>0)
   {
    /* suche gegenueber liegenden naechsten node  */
    rmin=MAXVALUE;
    for (j=0; j<set[set2].anz_n; j++ )
    {
      if ((nr2[j]>0)&&( node2[j].nr!= node1[i].nr))
      {
        dx= nx2[j]-nx1[i];
        dr= nr2[j]-nr1[i];
        R=sqrt( dx*dx + dr*dr );
        if (R<rmin)
        {
          rmin=R;
          node2j=j;
        }
      }
    }

    /* berechne den differenzwinkel  */
    phi[i]= nt2[node2j]-nt1[i];

    /* definiere den Zielwinkel, entweder vorgabe oder wie berechnet */
    if(phi_vorgabe==0.) phi_teilung=phi[i];
    else phi_teilung=phi_vorgabe;

    firstrun=1;
   nexttryz:;
    /* kontrolliere den differenzwinkel mit der teilung */
    dphi = phi_teilung - phi[i];
    if(dphi>2.*PI-DPHI_TOL) while (dphi>2.*PI-DPHI_TOL) dphi-=2.*PI;
    if(dphi<-2.*PI+DPHI_TOL) while (dphi<-2.*PI+DPHI_TOL) dphi+=2.*PI;
    if ((dphi*dphi > DPHI_TOL)&&(firstrun))
    {
      firstrun=0;
      phi_teilung=-phi_vorgabe;
      goto nexttryz;
    }
    else if ((dphi*dphi > DPHI_TOL)&&(!firstrun))
    {
      errMsg ("ERROR: korresponding node too far away:%lf grd, see set %s\n",dphi*180./PI, specialset->nompc);
      sprintf( buffer, "%d", node1[i].nr); 
      pre_seta(specialset->nompc, "n", buffer);
    }
    else 
    {
    if(printFlag) printf(" theta(%d):%lf theta(%d):%lf  dtheta:%lf dtheta_corr:%lf rmin:%lf\n",
      node1[i].nr, nt1[i]*180./PI, node2[node2j].nr, nt2[node2j]*180./PI,
      phi[i]*180./PI, phi_teilung*180./PI, rmin);

    if (corr[0]=='c')
    { 
      /* versetze den gefundenen Knoten auf die korrespondierende pos. */
      /* der dependent node wird auf die pos des indep gesetzt */
      node[node1[i].nr].nz = node[node2[node2j].nr].nz;
      if ( nr1[i] )
      {
        node[node1[i].nr].nx = node[node2[node2j].nr].nx*cos(phi_teilung)-node[node2[node2j].nr].ny*sin(phi_teilung);
        node[node1[i].nr].ny = node[node2[node2j].nr].nx*sin(phi_teilung)+node[node2[node2j].nr].ny*cos(phi_teilung);
      }  
    }  


   if (csys=='t')
   {
    if (compare( format, "abq", 3)== 3)
    {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFT, 1.,
          node2[node2j].nr, DOFT, -1. );
    }
   }
   if (csys=='r')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -cos(phi_teilung),  node2[node2j].nr, DOFY, sin(phi_teilung) );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 3);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf, %d,%d,%.12lf\n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFX, -sin(phi_teilung),  node2[node2j].nr, DOFY, -cos(phi_teilung) );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UZ", 1.,
              node1[i].nr, "UZ", 1., node2[node2j].nr, "UZ", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UX", 1.,
              node2[node2j].nr, "UX", -cos(phi_teilung), node2[node2j].nr, "UY", sin(phi_teilung) );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, node1[i].nr, "UY", 1.,
              node2[node2j].nr, "UX", -sin(phi_teilung), node2[node2j].nr, "UY", -cos(phi_teilung) );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
                                                          node2[node2j].nr, DOFX, -cos(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFY, sin(phi_teilung) );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
                                                          node2[node2j].nr, DOFX, -sin(phi_teilung));
      fprintf(handle, ", ,%8d,%8d,%.12lf\n", node2[node2j].nr, DOFY, -cos(phi_teilung) );
      }
    }
   if (csys=='c')
    {
    if (compare( format, "abq", 3)== 3)
      {
      /* schreibe die EQUATIOS im Abaqusformat */
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "*EQUATION\n");
        fprintf(handle, "%d\n", 2);
        fprintf(handle, "%d,%d,%.12lf, %d,%d,%.12lf \n", node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    else if (compare( format, "ans", 3)== 3)
      {
      /* schreibe die EQUATIOS im Ansysformat */
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UX", 1.,
              node1[i].nr, "UX", 1., node2[node2j].nr, "UX", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UY", 1.,
              node1[i].nr, "UY", 1., node2[node2j].nr, "UY", -1. );
      neqn++;
      fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
        neqn, -1, "UZ", 1.,
              node1[i].nr, "UZ", 1., node2[node2j].nr, "UZ", -1. );
      }
    else if (compare( format, "nas", 3)== 3)
      {
      /* schreibe die EQUATIOS im Nastranformat */
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFX, 1.,
          node2[node2j].nr, DOFX, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFY, 1.,
          node2[node2j].nr, DOFY, -1. );
      fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n", neqn+1, node1[i].nr, DOFZ, 1.,
          node2[node2j].nr, DOFZ, -1. );
      }
    }
   sprintf( buffer, "%d", node1[i].nr); 
   pre_seta(specialset->mpc, "n", buffer);
    }
   }
  }
 }
 else errMsg("ERROR: no axis of symmetry was specified:%c \n\n", (unsigned char)axis);

 end:;

  i=getSetNr(specialset->nompc);
  if (i>-1) if (set[i].anz_n>0) printf(" WARNING:%d dependent nodes could not be connected, check set:%s\n", set[i].anz_n, set[i].name);

  fclose(handle);

  if(nx1) free(nx1);
  if(nx2) free(nx2);
  if(nt1) free(nt1);
  if(nt2) free(nt2);
  if(nr1) free(nr1);
  if(nr2) free(nr2);
  if(phi) free(phi);
  if(node1) free(node1);
  if(node2) free(node2);
  scalNodes ( anz->n, node, scale );
}




/* die koeffizienten der MPCs ergeben sich aus den Flaechenanteilen */
int calcCoefficients(  Nodes *node, int n0, CTri3 *ctri3, int  e, double *c)
{
  int n1,n2,n3;
  double v01[3],v02[3],v03[3],v12[3],v13[3],vNorm012[3],vNorm023[3],vNorm031[3],vNorm123[3],eNorm012[3],eNorm023[3],eNorm031[3],eNorm123[3];
  double ag,a1,a2,a3, sum_c;

  n1=ctri3[e].nod[0];
  n2=ctri3[e].nod[1];
  n3=ctri3[e].nod[2];
  v_result( &node[n0].nx, &node[n1].nx, v01);
  v_result( &node[n0].nx, &node[n2].nx, v02);
  v_result( &node[n0].nx, &node[n3].nx, v03);
  v_result( &node[n1].nx, &node[n2].nx, v12);
  v_result( &node[n1].nx, &node[n3].nx, v13);

  /* flaeche des tri3 *2 */
  v_prod( v12, v13, vNorm123 );
  v_norm( vNorm123, eNorm123 );
  ag=v_betrag(vNorm123);

  /* teilflaechen *2 */
  v_prod( v02, v03, vNorm023 ); v_norm( vNorm023, eNorm023 );
  v_prod( v03, v01, vNorm031 ); v_norm( vNorm031, eNorm031 );
  v_prod( v01, v02, vNorm012 ); v_norm( vNorm012, eNorm012 );
  a1=v_betrag(vNorm023);
  if(v_sprod(eNorm023, eNorm123) <0.) a1*=-1;
  a2=v_betrag(vNorm031);
  if(v_sprod(eNorm031, eNorm123) <0.) a2*=-1;
  a3=v_betrag(vNorm012);
  if(v_sprod(eNorm012, eNorm123) <0.) a3*=-1;

  /* coefficienten */
  c[0]= -1;
  c[1]= a1/ag;
  c[2]= a2/ag;
  c[3]= a3/ag;
  sum_c= c[1]+c[2]+c[3];

  /*
  printf(" eNorm123:%lf %lf %lf \n", eNorm123[0],eNorm123[1],eNorm123[2] );
  printf(" eNorm023:%lf %lf %lf \n", eNorm023[0],eNorm023[1],eNorm023[2] );
  printf(" eNorm031:%lf %lf %lf \n", eNorm031[0],eNorm031[1],eNorm031[2] );
  printf(" eNorm012:%lf %lf %lf \n", eNorm012[0],eNorm012[1],eNorm012[2] );
  printf(" v_sprod(eNorm023, eNorm123):%lf\n",  v_sprod(eNorm023, eNorm123)); 
  printf(" v_sprod(eNorm031, eNorm123):%lf\n",  v_sprod(eNorm031, eNorm123));
  printf(" v_sprod(eNorm012, eNorm123):%lf\n", v_sprod(eNorm012, eNorm123));
  printf(" sum_c:%lf c:%lf %lf %lf\n", sum_c,c[1],c[2],c[3] );
  */

  if ((sum_c<MIN_C)||(sum_c>MAX_C)) return(-1);
  return(1);
}


/* liefert MAXVALUE wenn der node ausserhalb liegt, */
/* ansonsten den kuerzesten Abstand zur ebene.     */
double find_tri3( Nodes *node, int n, CTri3 *ctri3, int e)
{
   int i;
   int n0,n1,n2, inull, iplus, iminus;
   double  vN0N1[3], vN1N2[3], vN2N0[3], vN0N[3], vN1N[3],  vN2N[3],
          vprod0[3], vprod1[3], vprod2[3], vsprod[3], vnorm[3];
   double en[3], ev[3], eu[3], vNN0[3], g,a;

   /* der node liegt im Dreieck wenn: */
   /* - berechne die Vektorprodukte zwischen den Kantenvektoren und dem Vektor von den    */
   /*   Kantenpunkten zu dem node (v_prod= vP1P2 x vP1Pn)                                 */
   /* - berechne die Scalarprtodukte v_sprod zwischen den v_prod und dem Normalenvektor   */
   /*   des Dreiecks. Wenn alle v_sprod positiv sind, dann liegt der node innerhalb und   */
   /*   davor, wenn alle negativ sind dann dahinter. Wenn uneinheitlich, dann ausserhalb. */

   n0=ctri3[e].nod[0];
   n1=ctri3[e].nod[1];
   n2=ctri3[e].nod[2];
   v_result( &node[n0].nx, &node[n1].nx, vN0N1);
   v_result( &node[n1].nx, &node[n2].nx, vN1N2);
   v_result( &node[n2].nx, &node[n0].nx, vN2N0);
   v_result( &node[n0].nx, &node[n].nx, vN0N);
   v_result( &node[n1].nx, &node[n].nx, vN1N);
   v_result( &node[n2].nx, &node[n].nx, vN2N);

   /* berechne den Normalenvektor auf der flaeche */
   v_prod( vN0N1, vN1N2, vnorm );
   v_norm( vnorm, en );
   /* berechne die einheitsvektoren der ebenengleichung des tri3 */
   v_norm( vN0N1, eu );
   v_norm( vN1N2, ev );
   /* bestimme den Abstand zwischen den Aufpunkten der Normalen und in n verschobenen Ebene  */
   v_result( &node[n].nx, &node[n0].nx, vNN0 );

   /* berechne die Konstante g (Abstand)  pn_neu=pn-en*g  */
   g = AsplitL( vNN0, eu, ev, en );
   v_prod( vN0N1, vN0N, vprod0 );
   v_prod( vN1N2, vN1N, vprod1 );
   v_prod( vN2N0, vN2N, vprod2 );
   vsprod[0]= v_sprod( vnorm, vprod0);
   vsprod[1]= v_sprod( vnorm, vprod1);
   vsprod[2]= v_sprod( vnorm, vprod2);

   /*   kontrolle ob ein vsprod=0 ist. Dann liegt naemlich                */
   /*   der zu kontrollierende node genau ueber einer der umrandungen     */
   /*   der kontroll-flaeche (vprod ist dann senkrecht auf der normalen). */
   /*   Dann werden vsprod mit den gleichen vorzeichen zusammen-          */
   /*   gezaelt, dabei gelten die nuller als joker                        */

   /* setze sehr kleine zahlen zu NULL */
   for (i=0; i<3; i++) { a=vsprod[i]*vsprod[i]; if(a<1.e-40)  vsprod[i]=0.; }


   inull=0;
   for (i=0; i<3; i++) if (vsprod[i] == 0.) inull++;

   iplus=inull;
   for (i=0; i<3; i++) if (vsprod[i] > 0.) iplus++;

   iminus=inull;
   for (i=0; i<3; i++) if (vsprod[i] < 0.) iminus++;
   /*
   printf (" vsprod: %le %le %le inull:%d iplus:%d iminus:%d offs:%lf\n",
       vsprod[0],vsprod[1],vsprod[2], inull, iplus, iminus, g );
   */
   /*           * wenn alle vectorprodukte das gleiche vorzeichen haben    *   */
   /*           * dann ist der node innerhalb der flaeche                  *   */

   if (iplus == 3) return(g);
   else if (iminus == 3) return(g);
   else return(MAXVALUE);
}


/* verschiebe den node */
void corrNode(  Nodes *node, int n, CTri3 *ctri3, int  e, double g )
{
   int n0,n1,n2;
   double  vN0N1[3], vN1N2[3], vnorm[3];
   double en[3], vNNneu[3], vNneu[3], gneu ;

   n0=ctri3[e].nod[0];
   n1=ctri3[e].nod[1];
   n2=ctri3[e].nod[2];
   v_result( &node[n0].nx, &node[n1].nx, vN0N1);
   v_result( &node[n1].nx, &node[n2].nx, vN1N2);

   /* berechne den Normalenvektor auf der flaeche */
   v_prod( vN0N1, vN1N2, vnorm );
   v_norm( vnorm, en );
   /* scaliere den Normalenvektor mit dem offset */
   gneu=g*-1.;
   v_scal( &gneu, en, vNNneu );
   v_result( vNNneu, &node[n].nx, vNneu );
   /*
   printf ("x:%lf xneu:%lf dx:%lf\n",node[n].nx,vNneu[0],vNNneu[0]);
   printf ("y:%lf yneu:%lf dy:%lf\n",node[n].ny,vNneu[1],vNNneu[1]);
   printf ("z:%lf zneu:%lf dz:%lf\n",node[n].nz,vNneu[2],vNNneu[2]);
   */
   /* verschiebe den node */
   node[n].nx= vNneu[0];
   node[n].ny= vNneu[1];
   node[n].nz= vNneu[2];
}


void areampc(int set1, int set2, unsigned char *format, unsigned char *value, unsigned char *corr, int flag)
{
  int  i, j, k=0, n, e, f;

  int    DOF[7]={0,1,1,1,0,0,0};
  unsigned char    ansy_dofs[6][5]={"UX","UY","UZ","ROTX","ROTY","ROTZ"}; /* SHORT-CUTS FOR ANSYS DOFS */

  int     sflag={0}, n_closest_nodes;      /* 0:abq, 1:ans, 2:nas equations, 3:interpolate data */

  unsigned char   datout[MAX_LINE_LENGTH];
  unsigned char   buffer[MAX_LINE_LENGTH];
  unsigned char   dofbuf[8];

  CTri3     *ctri3=NULL;                   /* triangulierte indep-nodes flaeche */
  static int **tri3_index;           /* am jeweiligen node haengenden dreiecke */
  int       *ntri_nodes=NULL;        /* anzahl der anhaengenden dreiecke       */
  int       sum_tri3;                /* anzahl der ctri3 */
  int       corrFlag, ini_corrFlag;

  FILE  *handle;

  int n0, n1, n2;
  int   indeql, elbuf=0, setall, anz_n;
  double dx,dy,dz;
  double  offset=0., min_offset,offsetbuf=0., tol;

  int   nface[8];
  double c[9],  coords[24], ratio[8];
  double dist, conode[3];
  double p0[3], p1[3], p2[3], p0p1[3], p0p2[3];
  int    settmp,  *surnod=NULL;

  Rsort *rsort=NULL;


  /* ------ check and set the format ---- */
  if (compare(format,"abq", 3) == 3)  sflag=0; 
  else if (compare(format,"ans", 3) == 3)  sflag=1;
  else if (compare(format,"nas", 3) == 3)  sflag=2;
  else 
  {
    errMsg("ERROR, format:%s not known \n\n", format);
    return;
  }

  /* ---- clear special sets if flag==0  ----- */
  if(!flag)
  {
    delSet(specialset->impc );
    delSet(specialset->mpc );
    delSet(specialset->nompc );
    delSet(specialset->noel );
  }
  /* else remove all already used dep-nodes from the set1 (dep-set) and also from set2 (ind-set) */
  /* and  remove all already used ind-nodes from the set1 */
  else
  {
    k=getSetNr(specialset->mpc);
    if(k>-1) for(i=0; i<set[k].anz_n; i++) { setr(set1,"n",set[k].node[i]); setr(set2,"n",set[k].node[i]); }
    k=getSetNr(specialset->impc);
    if(k>-1) for(i=0; i<set[k].anz_n; i++) setr(set1,"n",set[k].node[i]);
  }      


  /* Open the files and check if they were opened correctly */
  sprintf(datout, "%s.equ", set[set1].name);
  handle = fopen (datout, "w");
  if (handle==NULL) { printf ("\nThe output file \"%s\" could not be opened.\n\n", datout); return; }
  else  printf (" %s opened\n", datout);
  if (compare( format, "abq", 3)== 3)      fprintf(handle, "** areampc based on set %s %s\n",set[set1].name, set[set2].name );
  else if (compare( format, "ans", 3)== 3) fprintf(handle, "! areampc based on set %s %s\n",set[set1].name, set[set2].name );
  else if (compare( format, "nas", 3)== 3) fprintf(handle, "$ areampc based on set %s %s\n",set[set1].name, set[set2].name );

  /* determine the degrees of freedom */
  buffer[1]=0;
  for (i=0;i<6;i++)  DOF[i]=0;
  if (atoi(value)>0)
  { 
    for (i=0;i<6;i++)
    {
      buffer[0]=value[i];
      if (atoi(buffer)-1 >= 0) DOF[atoi(buffer)]=1;
      else if (buffer[0] == 't') DOF[0]=1;
    }  
  }
  else
  {
    /* entity of a dataset (loadcase) is given for interpolation of data */
    if(value[0]=='e')
    {
      if(corr[0]=='l')  DOF[0]=atoi(&value[1]); 
      else { printf(" ERROR in sequence for interpolation\n"); return; }
    }
    /* "slide" is defined, mpcs for sliding in a plane defined by the first dependent nodes */
    else if(value[0]=='s')
    {
      DOF[3]=1;
      /* define a set of nodes which define the slide-condition */
      if (compare( format, "abq", 3)== 3)
      {
        fprintf(handle, "*NSET,NSET=%s%s\n",set[set1].name, set[set2].name );
        for (i=0; i<set[set1].anz_n; i++ ) fprintf(handle, "%d,\n", set[set1].node[i]);  
        for (i=0; i<set[set2].anz_n; i++ ) fprintf(handle, "%d,\n", set[set2].node[i]);  

        /* determine the sliding plane */
        /* - search an element-face defined by dep-nodes (set1) */
        /* - get all dep-faces */
        delSet(specialset->tmp);
        if( (settmp=pre_seta( specialset->tmp, "i", 0 )) <0 ) return;
        for (k=0; k<set[set1].anz_n; k++)  seta( settmp, "n", set[set1].node[k]  );
        completeSet( specialset->tmp, "do");

        /* mark the surface nodes for easy element identification */
        if( (surnod=(int *)realloc((int *)surnod, (anz->nmax+1)*sizeof(int) ) )==NULL)
        { printf(" ERROR: malloc failure\n"); return; }
        for (i=0; i<=anz->nmax; i++) surnod[i]=0;
        for (i=0; i<set[set1].anz_n; i++) surnod[set[set1].node[i]]=1;

        for(f=0; f<set[settmp].anz_f; f++)
        {
          i=set[settmp].face[f];
          anz_n=n=0;
          if (face[i].type==7) anz_n=3;
          if (face[i].type==8) anz_n=6;
          if (face[i].type==9) anz_n=4;
          if (face[i].type==10) anz_n=8;
      
          if(anz_n)
          {
            for (k=0; k<anz_n; k++) if (surnod[face[i].nod[k]]) n++;
            if (n==anz_n) break;
	  }
	}
        n0=face[i].nod[0];
        n1=face[i].nod[1];
        n2=face[i].nod[2];
	if(printFlag) printf("n0:%d n1:%d n2:%d\n", n0, n1, n2);
        p0[0]=node[n0].nx*scale->w+scale->x;
        p0[1]=node[n0].ny*scale->w+scale->y;
        p0[2]=node[n0].nz*scale->w+scale->z;
        p1[0]=node[n1].nx*scale->w+scale->x;
        p1[1]=node[n1].ny*scale->w+scale->y;
        p1[2]=node[n1].nz*scale->w+scale->z;
        p2[0]=node[n2].nx*scale->w+scale->x;
        p2[1]=node[n2].ny*scale->w+scale->y;
        p2[2]=node[n2].nz*scale->w+scale->z;
        v_result( p0, p1, p0p1 );
        v_result( p0, p2, p0p2 );
        
        fprintf(handle, "*TRANSFORM,NSET=%s%s\n",set[set1].name, set[set2].name );
        fprintf(handle, "%lf, %lf, %lf, %lf, %lf, %lf\n", p0p1[0],p0p1[1],p0p1[2], p0p2[0],p0p2[1],p0p2[2] );
      }
    }
    else 
    {
      errMsg("ERROR, value:%s not known \n\n", value);
      return;
    }
  }

  /* set the correction flag to correct the node position */
  if (corr[0]=='c') ini_corrFlag=1;
  else ini_corrFlag=0;

  /* determine the starting nr of the equations for ansys */
  if ((corr[0]=='c')||(corr[0]=='u'))
  { if (atoi(&corr[1])>0) neqn=atoi(&corr[1])-1; }

  /* a loadcase is specified for interpolation */
  if (corr[0]=='l')
  {
    DOF[1]=atoi(&corr[1]);
    if (compare(format,"abq", 3) == 3)  sflag=3;
    else 
    {
      errMsg("ERROR, format:%s not known \n\n", format);
      return;
    }
  } 

  if(printFlag) printf ("datout:%s set1:%s nodes:%d set2:%s nodes:%d\n",datout, set[set1].name, set[set1].anz_n, set[set2].name, set[set2].anz_n);
  if(printFlag) printf ("DOFs:"); for(i=0;i<7;i++) if(printFlag) printf("%d", DOF[i]);
  if(printFlag) printf ("\n1st Equ.Nr| ID   -e:%d\n", neqn);
  if(printFlag) printf ("Tolerance for equal node -dr:%lf\n", gtol);
  if(printFlag) printf ("Tolerance for gap        -dA:%lf\n", 1.-MIN_C);
  /* if(printFlag) printf ("Tol for mismatch   -bail:%lf\n", BAILOUT); */


  /* ------- node-koordinaten berechnen und am ende wieder scalieren ------ */
  descalNodes ( anz->n, node, scale );


  /* Suche die elementflaechen, die durch die independent nodes beschrieben werden,       */
  /* und zerlege diese in dreiecke. Und speichere die zu jedem node gehoerenden dreiecke. */
  setall=getSetNr("all");
  if(setall>-1)
    sum_tri3 = makeTriFromElems(set2, setall, anz->nmax, set, e_enqire, &ctri3, &tri3_index, &ntri_nodes);
  else { printf("ERROR: set all dose not exist\n"); return; }

  if(!sum_tri3)
  {
    errMsg ("ERROR: found no valid element\n\n" );
    goto end;
  }
  if(printFlag) printf (" %d ctri3 created from %d elements\n\n", sum_tri3, set[0].anz_e );

#if TEST  
  for(i=0; i<sum_tri3; i++)
  {
    printf("%d e:%d s:%d nods: %d %d %d\n",i,
	   ctri3[i].elem_nr,
	   ctri3[i].group,  
	   ctri3[i].nod[0],
	   ctri3[i].nod[1],
	   ctri3[i].nod[2]);
  }
  for(i=0; i<set[set2].anz_n; i++)
  {
    printf("%d n:%d sum:%d", i,  set[set2].node[i], ntri_nodes[set[set2].node[i]]);
    for(j=0; j<ntri_nodes[set[set2].node[i]]; j++)  printf(" %d", tri3_index[set[set2].node[i]][j]);
    printf("\n");
  }
#endif

  /* suche nodes, berechne und schreibe EQUATION's  */

  if((int)N_CLOSEST_NODES<set[set2].anz_n) n_closest_nodes=(int)N_CLOSEST_NODES; else n_closest_nodes=set[set2].anz_n;
  tol=gtol/scale->w;
  tol*=tol;
  if ( (rsort = (Rsort *)malloc( (set[set2].anz_n+1) * sizeof(Rsort))) == NULL )
    printf("ERROR: realloc failed: Rsort\n\n" ); 

  for (i=0; i<set[set1].anz_n; i++ )
  {
    /* suche die naechst-liegenden indep-nodes  */
    if ( (rsort = (Rsort *)realloc((Rsort *)rsort, (set[set2].anz_n+1) * sizeof(Rsort))) == NULL )
      printf("ERROR: realloc failed: Rsort\n\n" );
    for (j=0; j<set[set2].anz_n; j++)
    {
      dx= node[set[set2].node[j]].nx - node[set[set1].node[i]].nx;
      dy= node[set[set2].node[j]].ny - node[set[set1].node[i]].ny;
      dz= node[set[set2].node[j]].nz - node[set[set1].node[i]].nz;      
      rsort[j].i=set[set2].node[j];
      rsort[j].r=dx*dx + dy*dy + dz*dz;
    }
    qsort( rsort, set[set2].anz_n, sizeof(Rsort), (void *)compareRsort );
#if TEST
    for (j=0; j<n_closest_nodes; j++)
      printf("%d n:%d r:%lf\n", j, rsort[j].i, sqrt(rsort[j].r)); 
#endif

    indeql=0;
    if ( rsort[0].r<tol ) /* IF 2 NODES ARE EQUAL */
    {
      if(printFlag) printf("node:%d, found equal node:%d with dr:%lf\n"
      , set[set1].node[i], rsort[0].i, sqrt(rsort[0].r));
      indeql=rsort[0].i;

      /* versetze den gefundenen Knoten auf die exakte korrespondierende pos. */
      if(ini_corrFlag)
      {
        node[set[set1].node[i]].nx = node[indeql].nx;
        node[set[set1].node[i]].ny = node[indeql].ny;
        node[set[set1].node[i]].nz = node[indeql].nz;
      }

      switch (sflag)
      {
        case 0:
        /* schreibe die EQUATIOS im Abaqusformat */
        for (e=0;e<7;e++)
        {
          if(DOF[e])
          {
            fprintf(handle, "*EQUATION\n");
            fprintf(handle, "%d\n", 2);
            if(e) fprintf(handle, "%d,%d,%.12lf,%d,%d,%.12lf \n", set[set1].node[i], e, -1., indeql, e, 1. );
            else fprintf(handle, "%d,%d,%.12lf,%d,%d,%.12lf \n", set[set1].node[i], DOFT, -1., indeql, DOFT, 1. );
          }
        }
        break;
        case 1:
        /* schreibe die EQUATIOS im Ansysformat */
        for (e=0;e<6;e++)
        {
          if(DOF[e+1])
          {
            neqn++;
            fprintf(handle, "CE,%d,0,%d,%s,%.12lf, %d,%s,%.12lf,  %d,%s,%.12lf\n",
            neqn, set[set1].node[i], ansy_dofs[e], 1., indeql, ansy_dofs[e], -1., -1, ansy_dofs[e], 1. );
          }
        }
        break;
        case 2:
        /* schreibe die EQUATIOS im NASTRANformat */
#if NASMPC
        for (e=1;e<7;e++)
        {
          if(DOF[e])
          {
            fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf,%8d,%8d,%.12lf\n"
            , neqn+1, set[set1].node[i],e,-1.,indeql,e,1.);
          }
        }
#else
        /* schreibe die EQUATIOS im Nastranformat als RBE2 */
        for(j=0; j<8; j++) dofbuf[j]=0;
        j=0; for(e=1; e<7; e++) { if(DOF[e]) { sprintf(&dofbuf[j],"%1d",e); j++; } }

        fprintf(handle, "RBE2,%8d,%8d,%8s,%8d\n", ++neqn, indeql, dofbuf, set[set1].node[i] );
        break;

        /* a loadcase is specified for interpolation, flag=node-offset */
        case 3:
          fprintf(handle, " %d, %f\n", set[set1].node[i]-flag, lcase[DOF[1]].dat[DOF[0]][indeql]);       
#endif
        break;
      }
    }
    else
    {
      if(printFlag)
        printf("node:%d, found non equal node:%d at dist:%lf\n", set[set1].node[i], rsort[0].i, sqrt(rsort[0].r));

      /* knoten liegt zwischen den indep-nodes, suche das passende element.       */
      /* fange mit den elementen des naechstliegenden nodes an, und kontrolliere   */
      /* mit dem vectorprodukt welche elementflaeche den node umschliest          */

      min_offset=MAXVALUE;
      for (n=0; n<n_closest_nodes; n++)
      {
        for (j=0; j<ntri_nodes[ rsort[n].i ]; j++)
        {
          e=tri3_index[ rsort[n].i ][j];
	  /*
	  if( set[set1].node[i]==3539) 
        //  printf("checke n:%d von e:%d  nod:%d %d %d\n", rsort[n].i, e+1, ctri3[e].nod[0],ctri3[e].nod[1],ctri3[e].nod[2] );
	  */
          offset=find_tri3( node, set[set1].node[i], ctri3, e);
          if( offset != MAXVALUE )
          {
            /*
	    if( set[set1].node[i]==3539) 
              printf(" found enclosing tri3:%d for node:%d, offset:%lf\n", e+1, set[set1].node[i], offset);
	    */
            /* merke dir das element und den offset */
            if (min_offset > offset*offset ) { min_offset=offset*offset;  elbuf=e; offsetbuf=offset;}
          }
        }
      }
      if (min_offset==MAXVALUE)
      {
        corrFlag=0;
        printf("WARNING: no enclosing element for dep-node:%d found, see set %s\n"
        , set[set1].node[i], specialset->noel );
        sprintf( buffer, "%d", set[set1].node[i]); 
        pre_seta(specialset->noel, "n", buffer);

        /* kontrolliere welches zum naechsten node gehoerende dreieck */
        /* relativ am naechsten liegt und ob der grenzwert unterschritten ist */
        /* kriterium: flaechenfehler aller tri-set[set1].node[i] poligone */
        for (j=0; j<ntri_nodes[ rsort[0].i ]; j++)
        {
          e=tri3_index[ rsort[0].i ][j];
#if TEST    	    
          printf("suche fuer n:%d das naechste Tri3 e:%d  nod:%d %d %d \n",
            rsort[0].i, e+1,ctri3[e].nod[0],ctri3[e].nod[1],ctri3[e].nod[2] );
#endif	    
          if ( calcCoefficients( node, set[set1].node[i], ctri3, e, c) != -1 )
          {
            offset=c[1]*c[1]+c[2]*c[2]+c[3]*c[3];
            if(offset<min_offset){ min_offset=offset; elbuf=e; }
#if TEST    
            printf(" qadsum:%lf coef:%lf %lf %lf\n",
              offset, c[3], c[1], c[2] );
#endif	    
          }    
	}
        if(min_offset==MAXVALUE)
        {
          printf("WARNING: no coefficients could be calculated, no MPC created for node:%d, see set %s\n", set[set1].node[i], specialset->nompc);
          goto create_no_mpc;
        }
        else    
        {
          printf(" but found a close element\n");
        }
      }
      else
      {
        corrFlag=ini_corrFlag;
        offset=offsetbuf;
        if(printFlag)
          printf("closest tri3:%d elemnr:%d (%d %d %d)for node:%d, offset:%lf\n", elbuf+1, ctri3[elbuf].elem_nr, ctri3[elbuf].nod[0],ctri3[elbuf].nod[1],ctri3[elbuf].nod[2], set[set1].node[i], offset);
      }    

      /* das umschliessende Tri3 ist nun bekannt, wenn die korrekte shapefunction des */
      /* Mutterelements noch nicht eingebaut ist, haenge den node direkt an das Tri3  */
      if ( e_enqire[ ctri3[elbuf].elem_nr ].type ==  1 )
      {
        /* berechnung der MPC-Koeffizienten fuer he8  */

        /* knoten der betroffenen elementseite filtern */
        switch(ctri3[elbuf].group)
        {
          case 1:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          break;
          case 2:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          break;
          case 3:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          break;
          case 4:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          break;
          case 5:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          break;
          case 6:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          break;
        }

        /*
        ataches node with coordinates in "conode" to the face containing 
        "nterms" nodes with coordinates in field "coords" (nterms < 9).
        */
        n=4;

        for (j=0;j<n;j++)
        {
          coords[j*3]=  node[nface[j]].nx; 
          coords[j*3+1]=node[nface[j]].ny; 
          coords[j*3+2]=node[nface[j]].nz;
          /*
          printf (" nface[%d]:%d x:%lf y:%lf z:%lf\n", n, nface[j],
          coords[j*3], coords[j*3+1], coords[j*3+2] );
          */
        }
        conode[0]=node[set[set1].node[i]].nx;
        conode[1]=node[set[set1].node[i]].ny;
        conode[2]=node[set[set1].node[i]].nz;
        attach_new(coords,conode,&n,ratio,&dist);
        c[0]=-1.;
        for(j=0; j<n; j++) c[j+1]=ratio[j];

        /* correct the node possition if requested */
        if(ini_corrFlag)
        {
          node[set[set1].node[i]].nx=conode[0];
          node[set[set1].node[i]].ny=conode[1];
          node[set[set1].node[i]].nz=conode[2];
        }
        k=5;
      }
      else if ( e_enqire[ ctri3[elbuf].elem_nr ].type == 4 )
      {
        /* berechnung der MPC-Koeffizienten fuer he20 */

        /* knoten der betroffenen elementseite filtern */
        switch(ctri3[elbuf].group)
        {
          case 1:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[8];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[9];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[10];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[11];
          break;
          case 2:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[8];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[13];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[16];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[12];
          break;
          case 3:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[9];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[14];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[17];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[13];
          break;
          case 4:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[10];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[15];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[18];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[14];
          break;
          case 5:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[11];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[12];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[19];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[15];
          break;
          case 6:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[16];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[17];
          nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[18];
          nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[19];
          break;
        }

        /*
        ataches node with coordinates in "conode" to the face containing 
        "nterms" nodes with coordinates in field "coords" (nterms < 9).
        */
        n=8;

        for (j=0;j<n;j++)
        {
          coords[j*3]=  node[nface[j]].nx; 
          coords[j*3+1]=node[nface[j]].ny; 
          coords[j*3+2]=node[nface[j]].nz;
          /*
          printf (" nface[%d]:%d x:%lf y:%lf z:%lf\n", n, nface[j],
          coords[j*3], coords[j*3+1], coords[j*3+2] );
          */
        }
        conode[0]=node[set[set1].node[i]].nx;
        conode[1]=node[set[set1].node[i]].ny;
        conode[2]=node[set[set1].node[i]].nz;
        attach_new(coords,conode,&n,ratio,&dist);
        c[0]=-1.;
        for(j=0; j<n; j++) c[j+1]=ratio[j];

        /* correct the node possition if requested */
        if(ini_corrFlag)
        {
          node[set[set1].node[i]].nx=conode[0];
          node[set[set1].node[i]].ny=conode[1];
          node[set[set1].node[i]].nz=conode[2];
        }
        k=9;
      }
      else if ( e_enqire[ ctri3[elbuf].elem_nr ].type == 6 )
      {
        /* berechnung der MPC-Koeffizienten fuer Tet10 */

        /* knoten der betroffenen elementseite filtern */
        switch(ctri3[elbuf].group)
        {
          case 1:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[8];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          break;
          case 2:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[9];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[8];
          break;
          case 3:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[9];
          break;
          case 4:
          nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
          nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
          nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
          nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
          nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
          nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
          break;
        }

        /*
        ataches node with coordinates in "conode" to the face containing 
        "nterms" nodes with coordinates in field "coords" (nterms < 9).
        */
        n=6;

        for (j=0;j<n;j++)
        {
          coords[j*3]=  node[nface[j]].nx; 
          coords[j*3+1]=node[nface[j]].ny; 
          coords[j*3+2]=node[nface[j]].nz;
          /*
          printf (" ind_n[%d]:%d x:%lf y:%lf z:%lf\n", j, nface[j], coords[j*3], coords[j*3+1], coords[j*3+2] );
          */
        }
        conode[0]=node[set[set1].node[i]].nx;
        conode[1]=node[set[set1].node[i]].ny;
        conode[2]=node[set[set1].node[i]].nz;
	// printf("dep:%d\n", set[set1].node[i]);
        attach_new(coords,conode,&n,ratio,&dist);
        c[0]=-1.;
        for(j=0; j<n; j++) c[j+1]=ratio[j];

        /* correct the node possition if requested */
        if(ini_corrFlag)
        {
          node[set[set1].node[i]].nx=conode[0];
          node[set[set1].node[i]].ny=conode[1];
          node[set[set1].node[i]].nz=conode[2];
        }
        k=7;
      }
      else if ( e_enqire[ ctri3[elbuf].elem_nr ].type == 8 )
      {
        /* berechnung der MPC-Koeffizienten fuer tr6  */

        nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
        nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
        nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
        nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
        nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
        nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];

        /*
        ataches node with coordinates in "conode" to the face containing 
        "nterms" nodes with coordinates in field "coords" (nterms < 9).
        */
        n=6;

        for (j=0;j<n;j++)
        {
          coords[j*3]=  node[nface[j]].nx; 
          coords[j*3+1]=node[nface[j]].ny; 
          coords[j*3+2]=node[nface[j]].nz;
          /*
          printf (" nface[%d]:%d x:%lf y:%lf z:%lf\n", n, nface[j],
          coords[j*3], coords[j*3+1], coords[j*3+2] );
          */
        }
        conode[0]=node[set[set1].node[i]].nx;
        conode[1]=node[set[set1].node[i]].ny;
        conode[2]=node[set[set1].node[i]].nz;
        attach_new(coords,conode,&n,ratio,&dist);
        c[0]=-1.;
        for(j=0; j<n; j++) c[j+1]=ratio[j];

        /* correct the node possition if requested */
        if(ini_corrFlag)
        {
          node[set[set1].node[i]].nx=conode[0];
          node[set[set1].node[i]].ny=conode[1];
          node[set[set1].node[i]].nz=conode[2];
        }
        k=7;
      }
      else if ( e_enqire[ ctri3[elbuf].elem_nr ].type == 10 )
      {
        /* berechnung der MPC-Koeffizienten fuer qu8  */

        nface[0]=e_enqire[ ctri3[elbuf].elem_nr ].nod[0];
        nface[1]=e_enqire[ ctri3[elbuf].elem_nr ].nod[1];
        nface[2]=e_enqire[ ctri3[elbuf].elem_nr ].nod[2];
        nface[3]=e_enqire[ ctri3[elbuf].elem_nr ].nod[3];
        nface[4]=e_enqire[ ctri3[elbuf].elem_nr ].nod[4];
        nface[5]=e_enqire[ ctri3[elbuf].elem_nr ].nod[5];
        nface[6]=e_enqire[ ctri3[elbuf].elem_nr ].nod[6];
        nface[7]=e_enqire[ ctri3[elbuf].elem_nr ].nod[7];

        /*
        ataches node with coordinates in "conode" to the face containing 
        "nterms" nodes with coordinates in field "coords" (nterms < 9).
        */
        n=8;

        for (j=0;j<n;j++)
        {
          coords[j*3]=  node[nface[j]].nx; 
          coords[j*3+1]=node[nface[j]].ny; 
          coords[j*3+2]=node[nface[j]].nz;
          /*
          printf (" nface[%d]:%d x:%lf y:%lf z:%lf\n", n, nface[j],
          coords[j*3], coords[j*3+1], coords[j*3+2] );
          */
        }
        conode[0]=node[set[set1].node[i]].nx;
        conode[1]=node[set[set1].node[i]].ny;
        conode[2]=node[set[set1].node[i]].nz;
        attach_new(coords,conode,&n,ratio,&dist);
        c[0]=-1.;
        for(j=0; j<n; j++) c[j+1]=ratio[j];

        /* correct the node possition if requested */
        if(ini_corrFlag)
        {
          node[set[set1].node[i]].nx=conode[0];
          node[set[set1].node[i]].ny=conode[1];
          node[set[set1].node[i]].nz=conode[2];
        }
        k=9;
      }
      else
      {
        /* Alle anderen Elemente: Berechnung der MPC-Koeffizienten fuer Tri3 */

        nface[0]=ctri3[elbuf].nod[0];
        nface[1]=ctri3[elbuf].nod[1];
        nface[2]=ctri3[elbuf].nod[2];
        if(printFlag) printf("   enclosing nodes:%d %d %d\n", nface[0],nface[1],nface[2] );

        if(corrFlag)
	{
          /* verschiebung des dep nodes ins tri3-element */
          corrNode( node, set[set1].node[i], ctri3, elbuf, offset );
           /* ueberpruefung der neuen position */
          if(printFlag) printf (" dist %lf\n", offset);
          offset=find_tri3( node, set[set1].node[i], ctri3, elbuf);
          if(printFlag) printf (" dist after corr %lf\n", offset);
        }
        /* bestimmung der coeffizienten */
        if ( calcCoefficients( node, set[set1].node[i], ctri3, elbuf, c) == -1 )
        {
          printf("WARNING: no coefficients could be calculated, no MPC created for node:%d, see set %s\n", set[set1].node[i], specialset->nompc);
          goto create_no_mpc;
        }    
        k=4;
      }

      /* Die Koeffizienten c sind nun bekannt */
      /* setze den koeffizienten gleich der summe der indep-koeffizienten */
      c[0]=0.;
      for (n=1;n<k;n++) c[0]-= c[n];
      if(printFlag) printf ("sum_c=%lf (should be 1)\n", -c[0]);

#if TEST
      /* schreibe die EQUATIOS im Abaqusformat auf den Schirm */
      for (e=0;e<7;e++)
      {
        if(DOF[e])
        {
          printf( "*EQUATION\n");
          printf( "%d\n", k);
          if(e)
          {
            printf("%d,%d,%.12lf \n", set[set1].node[i], e, c[0]);
            for (n=1;n<k;n++)
              printf("%d,%d,%.12lf \n", nface[n-1], e, c[n] );
          }
          else
          {
            printf("%d,%d,%.12lf \n", set[set1].node[i], DOFT, c[0]);
            for (n=1;n<k;n++)
              printf("%d,%d,%.12lf \n", nface[n-1], DOFT, c[n] );
          }
        }
      }
      printf("\n");
#endif

      switch (sflag)
      {
        case 0:
        for (e=0;e<7;e++)
        {
          if(DOF[e])
          {
            fprintf(handle, "*EQUATION\n");
            fprintf(handle, "%d\n", k);
            if(e)
            {
              fprintf(handle, "%d,%d,%.12lf\n", set[set1].node[i], e, c[0]);
              for (n=1;n<k;n++)
                fprintf(handle, "%d,%d,%.12lf\n", nface[n-1], e, c[n] );
            }
            else
            {
              fprintf(handle, "%d,%d,%.12lf\n", set[set1].node[i], DOFT, c[0]);
              for (n=1;n<k;n++)
                fprintf(handle, "%d,%d,%.12lf\n", nface[n-1], DOFT, c[n] );
            }
          }
        }
        break;
        case 1:
        /* schreibe die EQUATIOS im Ansysformat */
        for (e=0;e<6;e++)
        {
          if(DOF[e+1])
          {
            neqn++;
            fprintf(handle, "CE,%d,0,%d,%s,%.12lf\n", neqn, set[set1].node[i], ansy_dofs[e], c[0]);
            for (n=1;n<k;n++)
              fprintf(handle, "CE,%d,0,%d,%s,%.12lf\n", neqn, nface[n-1], ansy_dofs[e], c[n]);
          }
        }
        break;
        case 2:
        /* schreibe die EQUATIOS im NASTRANformat */
#if NASMPC
        for (e=1;e<7;e++)
        {
          if(DOF[e])
          {
             fprintf(handle, "MPC,%8d,%8d,%8d,%.12lf\n", neqn+1, set[set1].node[i], e, c[0]);
             for (n=1;n<k;n++)
               fprintf(handle, ", ,%8d,%8d,%.12lf\n", nface[n-1], e, c[n] );
          }
        }
#else
        /* schreibe die EQUATIOS im Nastranformat als RBE3 */
        /* RBE3     12051           111693  6       1.      123     111584  111659 */
        /*         111685  111694 */
        for(j=0; j<8; j++) dofbuf[j]=0;
        j=0; for(e=1; e<7; e++) { if(DOF[e]) { sprintf(&dofbuf[j],"%1d",e); j++; } }

        fprintf(handle, "RBE3,%8d,        ,%8d,%8s,      1.,%8s,%8d,%8d\n", ++neqn, set[set1].node[i], dofbuf, dofbuf, nface[0], nface[1]);
        fprintf(handle,","); for (n=2;n<k-1;n++) fprintf(handle, ",%8d",nface[n]); fprintf(handle,"\n");
        break;
        /* a loadcase is specified for interpolation, flag=node-offset*/
        case 3:
          c[0]=0.;
          for (n=1;n<k;n++) c[0]+=lcase[DOF[1]].dat[DOF[0]][nface[n-1]]*c[n];
          fprintf(handle, " %d, %f\n", set[set1].node[i]-flag, c[0]);       
#endif
        break;
      }
    }
    goto create_mpc;
    create_no_mpc:;
        sprintf( buffer, "%d", set[set1].node[i]); 
        pre_seta(specialset->nompc, "n", buffer);
    goto cont;
    create_mpc:;  
        sprintf( buffer, "%d", set[set1].node[i]); 
        pre_seta(specialset->mpc, "n", buffer);
        if(indeql)
	{
          sprintf( buffer, "%d", indeql); 
          pre_seta(specialset->impc, "n", buffer);
	}
        else for (n=1;n<k;n++)
	{
          sprintf( buffer, "%d", nface[n-1]); 
          pre_seta(specialset->impc, "n", buffer);
	}
    cont:;
  }
  if(rsort) free(rsort);

 end:;

  i=getSetNr(specialset->nompc);
  if (i>-1) if (set[i].anz_n>0) printf(" WARNING:%d dependent nodes could not be connected, check set:%s\n", set[i].anz_n, set[i].name);

  fclose(handle);
  if(ntri_nodes) free(ntri_nodes);
  /* if(tri3_index) free(tri3_index); do not free, otherwise subfields must be freed as well */
  if(ctri3) free(ctri3);
  scalNodes ( anz->n, node, scale );

  /* correct also all midside nodes of the dependent side elements */
  /* add all dep nodes to set tmp */
  if(set[set1].anz_n>0)
  {
    delSet(specialset->tmp);
    if( (settmp=pre_seta( specialset->tmp, "i", 0 )) <0 ) return;
    for (k=0; k<set[set1].anz_n; k++)  seta( settmp, "n", set[set1].node[k]  );
    completeSet( specialset->tmp, "up");

    fixMidsideNodes(specialset->tmp, "");

    /* clear special set  */
    delSet(specialset->ori);
  }
}



void gap(unsigned char *record)
{
  int  i,j, length;
  int setNr1, setNr2, enr, nn[2], nmin, *n_used, jmin;
  double offset, vdir[3], tol=0.17, edir[3], en1n2[3], n1n2[3], varea[3], area, min_area;
  unsigned char format[MAX_LINE_LENGTH], type[MAX_LINE_LENGTH];
  unsigned char  set1[MAX_LINE_LENGTH], set2[MAX_LINE_LENGTH], prognam[MAX_LINE_LENGTH];
  FILE *handle;

  length = sscanf(record, "%s%s%s%s%lf%lf%lf%lf", set1, set2, format, type, &vdir[0], &vdir[1], &vdir[2], &tol);
  if (compare( format, "abq", 3)!= 3)
  {
    errMsg(" ERROR: format:%s not yet supported\n", format );
  }
  setNr1=getSetNr(set1);
  setNr2=getSetNr(set2);
  
  strcpy ( prognam, set1);
  length= strlen ( set1 );
  strcpy (&prognam[length], ".gap");
  handle = fopen (prognam, "w");
  if ( handle== NULL )
  {
    printf ("\nThe input file %s could not be opened.\n\n", prognam); 
    return;
  }

  v_norm(vdir,edir); 
  if((n_used = (int *)malloc((set[setNr2].anz_n+2) * sizeof(int))) == NULL )
    printf("\n\n ERROR: malloc failure\n\n" );
  for(j=0; j<set[setNr2].anz_n; j++) n_used[j]=0;
  

  fprintf(handle, "** gap based on %s\n", set1);
  for(i=0; i<set[setNr1].anz_n; i++)
  {
    nn[0]=set[setNr1].node[i];

    /* search the correct second node for each gap-element */
    /* go over all nodes of set2 and calculate the cross-prodiuct between the normalized vectors edir and en1n2 */
    /* the n2 which gives min-cross-product is the closest */
    min_area=MAXVALUE;
    jmin=nmin=-1;
    
    for(j=0; j<set[setNr2].anz_n; j++) if(n_used[j]==0)
    {
      nn[1]=set[setNr2].node[j];
      v_result( &node[nn[0]].nx, &node[nn[1]].nx, n1n2);
      v_norm(n1n2, en1n2);
      v_prod(edir, en1n2, varea);
      area=v_betrag(varea);
      if(area<min_area) { min_area=area; nmin=nn[1]; jmin=j; }
    }
    if((jmin>-1) && (nn[1]!=nn[0]) && (min_area<tol) )
    {
      n_used[jmin]=1;
      nn[1]=nmin;
      enr=anz->emax+1;
      fprintf(handle, "*ELEMENT, TYPE=GAPUNI, ELSET=E%s%d\n", set1, i);   
      fprintf(handle, "%d, %d, %d\n",enr+i,nn[0],nn[1]);
/*
      elem_define( enr, 11, nn, 1, 0 );
      fprintf(handle, "%d, %d, %d\n",enr,nn[0],nn[1]);
*/

      /* offset is the initial distance in vdir direction */
      v_result( &node[nn[0]].nx, &node[nn[1]].nx, n1n2);
      offset=v_sprod(n1n2,edir);
      offset*=scale->w;
      fprintf(handle, "*GAP,ELSET=E%s%d\n", set1, i);
      fprintf(handle, "%lf, %lf, %lf, %lf\n",offset, vdir[0], vdir[1], vdir[2]);
      printf(" nn0:%d  nn1:%d minarea:%lf offset:%lf\n", nn[0], nn[1], min_area, offset);
    }
    else
    {
      printf(" nn0:%d  nn1:%d minarea:%lf not connected\n", nn[0], nn[1], min_area);
    }
  }

  fclose(handle);
  free(n_used);
}

