/* Read a CASTEP .phonon file. */

/* MJR (c) 2024 */

#include<stdio.h>
#include<stdlib.h> /* malloc */
#include<string.h>
#include<ctype.h>

#include "c2xsf.h"

#define LINE_SIZE 200

void phonon_read(FILE* infile, struct unit_cell *c, struct contents *m,
                 struct kpts *q, struct symmetry *s, struct es *ph){
  int nions,nbands,nqpts,itmp,i,j,n,dummy;
  char buffer[LINE_SIZE+1],*cptr;
  
  /* Read header */

  nions=nbands=nqpts=0;
  while(1){
    if (!fgets(buffer,LINE_SIZE,infile)) error_exit("Unexpected EOF");
    cptr=buffer;
    while (*cptr==' ') cptr++;
    if (!strncasecmp(cptr,"BEGIN header",12)) break;
  }

  while(1){
    if (!fgets(buffer,LINE_SIZE,infile)) error_exit("Unexpected EOF");
    cptr=buffer;
    while (*cptr==' ') cptr++;
    if (*cptr=='#') continue;
    if (!strncasecmp(cptr,"END header",10)) break;
    if (!strncasecmp(cptr,"Number of ions",14)){
      cptr+=14;
      if (sscanf(cptr,"%d",&nions)!=1)
	error_exit("error parsing number of ions");
      continue;
    }
    if (!strncasecmp(cptr,"Number of branches",18)){
      cptr+=18;
      if (sscanf(cptr,"%d",&nbands)!=1)
	error_exit("error parsing number of bands");
      continue;
    }
    if (!strncasecmp(cptr,"Number of wavevectors",21)){
      cptr+=21;
      
      if (sscanf(cptr,"%d",&nqpts)!=1)
	error_exit("error parsing number of qpts");
      continue;
    }
    if (!strncasecmp(cptr,"Unit cell vectors (A)",21)){
      c->basis=malloc(9*sizeof(double));
      if (!c->basis) error_exit("malloc error for basis");
      for(i=0;i<3;i++){
	fgets(buffer,LINE_SIZE,infile);
	if (multi_scan(buffer,c->basis[i],3,NULL)!=3)
	  error_exit("error parsing cell vectors");
      }
      real2rec(c);
      continue;
    }
    if (!strncasecmp(cptr,"Fractional Co-ordinates",23)){
      fprintf(stderr,"Reading %d atoms\n",nions);
      m->atoms=malloc(nions*sizeof(struct atom));
      if (!m->atoms) error_exit("malloc errror for atoms");
      for(i=0;i<nions;i++){
	if (!fgets(buffer,LINE_SIZE,infile)) error_exit("Unexpected EOF");
	if (sscanf(buffer,"%d%n",&dummy,&n)!=1)
	  error_exit("Error parsing atom");
	cptr=buffer+n;
	if (multi_scan(cptr,m->atoms[i].frac,3,&n)!=3)
	  error_exit("Error parsing atom");
	cptr+=n;
	while(isspace(*cptr)) cptr++;
	n=0;
	while(isalpha(cptr[n])) n++;
	cptr[n]=0;
	m->atoms[i].atno=atsym2no(cptr);
      }
      m->n=nions;
    }
    //    fprintf(stderr,"Unread:\n%s\n",buffer);
  }
  
  if (m->n) addabs(m->atoms,m->n,c->basis);

  if ((q==NULL)||(ph==NULL)) {
    fprintf(stderr,"Phonon data not read\n");
    return;
  }

  if (debug)
    fprintf(stderr,"Reading %d bands at each of %d q-points\n",
	    nbands,nqpts);

  ph->nbands=nbands;
  ph->nspins=1;
  q->n=nqpts;
  
  itmp=nbands*nqpts;
  if (itmp==0) error_exit("One of nbands and nqpts is zero!");
  ph->eval=malloc(itmp*sizeof(double));
  if (!ph->eval) error_exit("Malloc error for eigenvalues");
  q->kpts=malloc(nqpts*sizeof(struct atom));
  if (!q->kpts) error_exit("Malloc error for qpts");
  init_atoms(q->kpts,nqpts);
  
    /* Read k-points and evalues */

  i=0;
  while(i<nqpts){
    if (!fgets(buffer,LINE_SIZE,infile)) error_exit("Unexpected EOF");
    cptr=buffer;
    while (isspace(*cptr)) cptr++;
    if (strncmp(cptr,"q-pt=",5)) continue;
    cptr+=5;
    itmp=-1;
    sscanf(cptr,"%d%n",&itmp,&n);
    if (itmp!=i+1) error_exit("inconsistency in qpt numbering");
    cptr+=n;
    if (sscanf(cptr,"%lf %lf %lf %lf",
               q->kpts[i].frac,q->kpts[i].frac+1,q->kpts[i].frac+2,
	       &(q->kpts[i].wt))!=4)
      error_exit("Error parsing qpoint line");
    for(j=0;j<nbands;j++){
      if (!fgets(buffer,LINE_SIZE,infile)) error_exit("Unexpected EOF");
      cptr=buffer;
      while (isspace(*cptr)) cptr++;
      itmp=-1;
      sscanf(cptr,"%d%n",&itmp,&n);
      if (itmp!=j+1) error_exit("inconsistency in band numbering");
      cptr+=n;
      if (sscanf(cptr,"%lf",ph->eval+i*nbands+j)!=1)
	error_exit("error parsing evals");
    }
    i++;
  }

}
