/*
  meam-baskes.cpp
  by Wei Cai  caiwei@mit.edu
  Last Modified : Thu Aug 31 00:02:37 2006

  FUNCTION  : MD++ with MEAM potential (using Baskes Dyn88)
*/

#include "meam-baskes.h"


void MEAMFrame::Alloc()
{
    MDFrame::Alloc();
}    

void MEAMFrame::potential()
{
    MEAM();
}

void MEAMFrame::readMEAM()
{
    int i;
    
    inter_(); /* read MEAM parameters */

    if(cneigh_.dradn<0)
        cneigh_.dradn = 0.1*interact_.rcut;

    interact_.rcutsq = interact_.rcut*interact_.rcut;
    
    _RLIST= interact_.rcut + cneigh_.dradn;
    _SKIN = cneigh_.dradn;

    cneigh_.rctsqn = _RLIST*_RLIST;

    for(i=0;i<types_.ntypes;i++)
    {
        if (cmin0[i]>0)
        {
            scr_.cmin[i][i][i]=cmin0[i];
        }
    }
    
    //INFO_Printf("cmin=%e\n",scr_.cmin[0][0][0]);
    WARNING("***************************************************************************");
    WARNING("The MEAM potential is only implemented for rectangular supercells!");
    WARNING("It won't work correctly for tilted supercells (e.g. with dislocation dipole)");
    WARNING("***************************************************************************");
}

void MEAMFrame::MEAM()
{
    Vector3 h;
    int i, j;
    double eps;

    /*refreshneighborlist();*/
    
    lattice_.natoms=_NP;
    SHtoR();
    for(i=0;i<_NP;i++)
    {
        particle_.rv[i][0]=_R[i].x;
        particle_.rv[i][1]=_R[i].y;
        particle_.rv[i][2]=_R[i].z;
        particle_.itype[i] = species[i]+1;
    }
    lattice_.perlen[0]=_H[0][0];
    lattice_.perlen[1]=_H[1][1];
    lattice_.perlen[2]=_H[2][2];

    eps=1e-8;
    if ( (fabs(_H[0][1])>eps)||(fabs(_H[0][2])>eps)||
         (fabs(_H[1][0])>eps)||(fabs(_H[1][2])>eps)||
         (fabs(_H[2][0])>eps)||(fabs(_H[2][1])>eps) )
    {
        _INFO(_H);
        WARNING(" Only rectangular supercell is allowed!");
    }

//    INFO_Printf("lattice_.natoms=%d\n",lattice_.natoms);
    force_();

    _EPOT=0;
    for(i=0;i<_NP;i++)
    {
        _F[i].set(forces_.f[i][0],forces_.f[i][1],forces_.f[i][2]);
        _EPOT_IND[i] = forces_.e[i];
        _EPOT += forces_.e[i];
    }
    for(i=0;i<3;i++)
        for(j=0;j<3;j++)
            _VIRIAL[i][j]=forces_.stresst[i][j];
}

void MEAMFrame::initvars()
{
    MDFrame::initvars();
}

void MEAMFrame::initparser()
{
    MDFrame::initparser();
    bindvar("meamfile",mea_.meamf,STRING);
    bindvar("meafile",mea_.meafile,STRING);
    bindvar("ntypes",&types_.ntypes,INT);
    bindvar("ename0",cmeam_.enames[0],STRING);
    bindvar("ename1",cmeam_.enames[1],STRING);
    bindvar("ename2",cmeam_.enames[2],STRING);
    bindvar("rcut",&interact_.rcut,DOUBLE);
    bindvar("cmin0",cmin0,DOUBLE);    
    bindvar("kode0",kodes_.kodes[0],STRING);    
}

int MEAMFrame::exec(char *name)
{
    if(MDFrame::exec(name)==0) return 0;
    bindcommand(name,"readMEAM",readMEAM());
    return -1;
}
   
#ifdef _TEST

/* Main Program Begins */
class MEAMFrame meam;

int main(int argc, char *argv[])
{
    meam.initvars();
    meam.parse(SCParser::getfilehandler(argc,argv));
    return 0;
}

#endif//_TEST






























































/* old code */
#if 0

inline double interp(double func[],double deriv[],double dr,int ind,double qq)
{
    double f, a, b, c, d, f1, p1, A1, A2, dr2, dr3, qq2, qq3;
//    f = func[ind] + qq*deriv[ind];
    dr2=dr*dr; dr3=dr2*dr;
    qq2=qq*qq; qq3=qq2*qq;
    a = func[ind];
    b = deriv[ind];
    f1 = func[ind+1];
    p1 = deriv[ind+1];
    A1 = f1-a-b*dr;
    A2 = (p1-b)*dr;
    d = (A2-2*A1)/dr3;
    c = (3*A1-A2)/dr2;
    f=a+b*qq+c*qq2+d*qq3;
    return f;
}
    
    
inline double interp1(double func[],double deriv[],double dr,int ind,double qq)
{
    double fp, a, b, c, d, f1, p1, A1, A2, dr2, dr3, qq2, qq3;
//    fp = deriv[ind] + qq1/dr*(deriv[ind+1]-deriv[ind]);
    dr2=dr*dr; dr3=dr2*dr;
    qq2=qq*qq; qq3=qq2*qq;
    a = func[ind];
    b = deriv[ind];
    f1 = func[ind+1];
    p1 = deriv[ind+1];
    A1 = f1-a-b*dr;
    A2 = (p1-b)*dr;
    d = (A2-2*A1)/dr3;
    c = (3*A1-A2)/dr2;
    fp=b+2*c*qq+3*d*qq2;
    return fp;
}
#endif
