/* 
Author: Suri Bala
Copyright: Livermore Software Technology Corporation
Date: June, 2004
Input: binary ISF files Output: Text Formatted 
*/

#include<stdio.h> 
#include<stdarg.h> 
#include<math.h> 

#define WORDS 1*sizeof(int)
#define ISFMAX 10

typedef struct coord {
 float tc[3];
 float rc[3];
 struct coord *next;
} Coord;

typedef struct state {
 float time;
 struct coord *coord;
 struct state *next;
} State;

typedef struct node {
 int nid;
 struct coord *coord;
 struct node *next;
} Node;

Coord *chd=NULL,*ctmp=NULL,*ccur=NULL,*c_shead,*c_scur;
State *shd=NULL,*stmp=NULL,*scur=NULL;
Node *nhd=NULL,*ntmp=NULL,*ncur=NULL;

State *s_create(State *s);
Coord *c_create();
Node *n_create(Node *n);
void state_output(State *s);

int header[3],diskaddress[ISFMAX+1],type[ISFMAX];
FILE *f=NULL,*fo=NULL;

main (int argc, char *argv[])  {
 int i=0,j=0,k=0,tmp=0;
 
 if( argc < 2 ) {
  fprintf(stderr," Usage: isf isf_filename \n");
  exit(-1);
 } else {
  if( (f=fopen(argv[1],"r"))==NULL) {
    fprintf(stderr," Error: Could not open file %s\n", argv[1]);
    fprintf(stderr,"        Please check if the file exists\n");
    fprintf(stderr," Exiting ..\n");
    exit(-2);
  }
 }

 fo=fopen("isfoutput","w");

 fprintf(stderr," Reading Binary ISF file \n");
 /* read the first three header information; 0 - nsn, 1-ninterface, 2-dof */
 fread(header,1*WORDS,3,f);

 /* get disk address of connectivity : last word is not important */ 
 fread(diskaddress,1*WORDS,header[1]+1,f);
 
 /* get the type of interface : 0 - point, 1 - line , 2 - segments */
 fread(&type[i],1*WORDS,header[1],f);

 /* store node ids in linked list */
 fseek(f,diskaddress[0]*WORDS,SEEK_SET);
 for(i=0;i<header[0];i++) {
  fread(&tmp,WORDS,1,f); 
  ncur=n_create(ncur);
  ncur->nid=tmp;
 }

 /* go to the node coordinates disk address given by diskaddress[0]*WORDS bytes starting from disk address 0 */
 ntmp=nhd;
 
 fseek(f,diskaddress[1]*WORDS,SEEK_SET);
 for(j=0;j<header[0];j++) {
    ctmp=c_create();
    fread(&ctmp->tc,1*WORDS,3,f); 
    ntmp->coord=ctmp;
    ntmp=ntmp->next;
 }



 /* get time state */
 fprintf(stderr," getting time states ...");
 while(!feof(f)) {

  scur=s_create(scur);
  fread(&scur->time,1*WORDS,1,f); 

  /* read trans coords */
  for(j=0;j<header[0];j++) {
    if(j==0) {
        ctmp=c_create();
        c_shead=ctmp;
        scur->coord=c_shead;
        c_scur=scur->coord;
    }else {
       c_scur->next=c_create();
       c_scur=c_scur->next;
       ctmp=c_scur;
    }
    fread(&ctmp->tc,1*WORDS,3,f); 
  }

  /* read rot coords */
  ctmp=scur->coord;
  if(header[2]==6) {
   for(j=0;j<header[0];j++) {
     fread(&ctmp->rc,1*WORDS,3,f); 
     ctmp=ctmp->next;
   }
  }

 }/* end of while loop */

 fprintf(stderr," Closing Files \n");
 fclose(f);
 
 fprintf(stderr," Writing ISF data into file isfoutput \n");
 stmp=shd;
 state_output(stmp);

}


State *s_create(State *s) {
  if(s==NULL) {
     s=(State *)malloc(1*sizeof(State));
     s->next=NULL;
     shd=s;
   } else {
     s->next=(State *)malloc(1*sizeof(State));
     s=s->next;
     s->next=NULL;
   }
   if(s==NULL) { 
     fprintf(stderr," Failed to allocate memory. \n");
   }
   return(s);
}

Coord *c_create() {
  Coord *c;
   c=(Coord *)malloc(1*sizeof(Coord));
   c->next=NULL;
   return(c);
}

Node *n_create(Node *n) {
  if(n==NULL) {
     n=(Node *)malloc(1*sizeof(Node));
     n->coord=NULL;
     n->next=NULL;
     nhd=n;
   } else {
     n->next=(Node *)malloc(1*sizeof(Node));
     n->coord=NULL;
     n=n->next;
     n->next=NULL;
   }
   if(n==NULL) { 
     fprintf(stderr," Failed to create allocate memory. \n");
   }
   return(n);
}

void state_output(State *s) {
  int i=0;
  
  fprintf(fo,"*KEYWORD\n");
  fprintf(fo,"$*****************\n");
  fprintf(fo,"$* Model Summary *\n");
  fprintf(fo,"$*****************\n");
  fprintf(fo,"$  %10d interfaces found \n",header[1]);
  fprintf(fo,"$  %10d total number of interface nodes found per state dump \n",header[0]);
  fprintf(fo,"$  %10d degrees of freedom per node \n",header[2]);
  fprintf(fo,"$$********************************\n");
  fprintf(fo,"$* Initial Coordiantes of Nodes *\n");
  fprintf(fo,"$********************************\n");
  fprintf(fo,"$  Node Id        X              Y             Z     \n");
  fprintf(fo,"*NODE\n");
  ntmp=nhd;
  while(ntmp!=NULL) {
   fprintf(fo,"%8d,%16.8e,%16.8e,%16.8e,\n",
             ntmp->nid,ntmp->coord->tc[0],ntmp->coord->tc[1],ntmp->coord->tc[2]);
   ntmp=ntmp->next;
  }
  while(s!=NULL) {
    fprintf(fo,"$*********************************\n");
    fprintf(fo,"$* Current Time State = %10.4f   *\n",s->time);
    fprintf(fo,"$*********************************\n");
    fprintf(fo,"$  Node Id        X              Y             Z            RX         RY         RZ\n");
    fprintf(fo,"*NODE\n");
    while(s->coord!=NULL) {
     fprintf(fo,"%8d,%16.8e,%16.8e,%16.8e,",i+1,s->coord->tc[0],s->coord->tc[1],s->coord->tc[2]);
     /*
     if(header[2]==6) {
      fprintf(fo,"  %16.4e,%16.4f,%16.4e",s->coord->rc[0],s->coord->rc[1],s->coord->rc[2]);
     }
     */
     fprintf(fo,"\n");
     s->coord=s->coord->next;
     ++i;
    }
    i=0;
    s=s->next;
  }
  fprintf(fo,"*END\n");
}

/* Variables 
  header[3]      -> holds header information 
                   0 - number of isf nodes/state
                   1 - number of  interfaces
                   2 - number of degrees of freedom (3 for solid, 6 for shells)
  State        -> structure to hold the state information
                   for every time state, x,y,z,rx,ry,rz
                   prev and next pointer
  diskaddress[2]  -> holds diskaddress information for nodes
                      0 - start of node connectivity
                      1 - start of node coordinates at time zero
  f             -> input isf file pointer        
  fo            -> output file pointer
  *scur        -> State current pointer
  *shd       -> State head pointer
*/
