#include "pair_lcbop.h"
#include <mpi.h>
#include <cmath>
#include <cstring>
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "my_page.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define TOL 1.0e-9
#define PGDELTA 1
PairLCBOP::PairLCBOP(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
restartinfo = 0;
one_coeff = 1;
manybody_flag = 1;
ghostneigh = 1;
maxlocal = 0;
SR_numneigh = NULL;
SR_firstneigh = NULL;
ipage = NULL;
pgsize = oneatom = 0;
N = NULL;
M = NULL;
}
PairLCBOP::~PairLCBOP()
{
memory->destroy(SR_numneigh);
memory->sfree(SR_firstneigh);
delete [] ipage;
memory->destroy(N);
memory->destroy(M);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cutghost);
delete [] map;
}
}
void PairLCBOP::compute(int eflag, int vflag)
{
ev_init(eflag,vflag);
SR_neigh();
FSR(eflag,vflag);
FLR(eflag,vflag);
if (vflag_fdotr) virial_fdotr_compute();
}
void PairLCBOP::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cutghost,n+1,n+1,"pair:cutghost");
map = new int[n+1];
}
void PairLCBOP::settings(int narg, char **) {
if (narg != 0 ) error->all(FLERR,"Illegal pair_style command");
}
void PairLCBOP::coeff(int narg, char **arg)
{
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
error->all(FLERR,"Incorrect args for pair coefficients");
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
error->all(FLERR,"Incorrect args for pair coefficients");
for (int i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
} else if (strcmp(arg[i],"C") == 0) {
map[i-2] = 0;
} else error->all(FLERR,"Incorrect args for pair coefficients");
}
read_file(arg[2]);
spline_init();
int n = atom->ntypes;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
void PairLCBOP::init_style()
{
if (atom->tag_enable == 0)
error->all(FLERR,"Pair style LCBOP requires atom IDs");
if (force->newton_pair == 0)
error->all(FLERR,"Pair style LCBOP requires newton pair on");
int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->ghost = 1;
int create = 0;
if (ipage == NULL) create = 1;
if (pgsize != neighbor->pgsize) create = 1;
if (oneatom != neighbor->oneatom) create = 1;
if (create) {
delete [] ipage;
pgsize = neighbor->pgsize;
oneatom = neighbor->oneatom;
int nmypage = comm->nthreads;
ipage = new MyPage<int>[nmypage];
for (int i = 0; i < nmypage; i++)
ipage[i].init(oneatom,pgsize,PGDELTA);
}
}
double PairLCBOP::init_one(int i, int j)
{
if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
cut3rebo = 3.0 * r_2;
double cutmax = MAX( cut3rebo,r_2_LR );
cutghost[i][j] = r_2;
cutLRsq = r_2_LR*r_2_LR;
cutghost[j][i] = cutghost[i][j];
r_2_sq = r_2*r_2;
return cutmax;
}
void PairLCBOP::SR_neigh()
{
int i,j,ii,jj,n,allnum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq,dS;
int *ilist,*jlist,*numneigh,**firstneigh;
int *neighptr;
double **x = atom->x;
if (atom->nmax > maxlocal) { maxlocal = atom->nmax; memory->destroy(SR_numneigh);
memory->sfree(SR_firstneigh);
memory->destroy(N);
memory->destroy(M);
memory->create(SR_numneigh,maxlocal,"LCBOP:numneigh");
SR_firstneigh = (int **) memory->smalloc(maxlocal*sizeof(int *),
"LCBOP:firstneigh");
memory->create(N,maxlocal,"LCBOP:N");
memory->create(M,maxlocal,"LCBOP:M");
}
allnum = list->inum + list->gnum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ipage->reset();
for (ii = 0; ii < allnum; ii++) {
i = ilist[ii];
n = 0;
neighptr = ipage->vget();
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
N[i] = 0.0;
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < r_2_sq) {
neighptr[n++] = j;
N[i] += f_c(sqrt(rsq),r_1,r_2,&dS);
}
}
SR_firstneigh[i] = neighptr;
SR_numneigh[i] = n;
ipage->vgot(n);
if (ipage->status())
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
}
for (ii = 0; ii < allnum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
M[i] = 0.0;
jlist = SR_firstneigh[i];
jnum = SR_numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < r_2_sq) {
double f_c_ij = f_c(sqrt(rsq),r_1,r_2,&dS);
double Nji = N[j]-f_c_ij;
M[i] += f_c_ij * ( 1-f_c_LR(Nji, 2,3,&dS) );
}
}
}
}
void PairLCBOP::FSR(int eflag, int )
{
int i,j,jj,ii,inum;
tagint itag,jtag;
double delx,dely,delz,fpair,xtmp,ytmp,ztmp;
double r_sq,rijmag,f_c_ij,df_c_ij;
double VR,dVRdi,VA,Bij,dVAdi,dVA;
double del[3];
int *ilist,*SR_neighs;
double **x = atom->x;
double **f = atom->f;
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
SR_neighs = SR_firstneigh[i];
for (jj = 0; jj < SR_numneigh[i]; jj++) {
j = SR_neighs[jj];
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
r_sq = delx*delx + dely*dely + delz*delz;
rijmag = sqrt(r_sq);
f_c_ij = f_c( rijmag,r_1,r_2,&df_c_ij );
if (f_c_ij <= TOL) continue;
VR = A*exp(-alpha*rijmag);
dVRdi = -alpha*VR;
dVRdi = dVRdi*f_c_ij + df_c_ij*VR; VR *= f_c_ij;
VA = dVA = 0.0;
{
double term = B_1 * exp(-beta_1*rijmag);
VA += term;
dVA += -beta_1 * term;
term = B_2 * exp(-beta_2*rijmag);
VA += term;
dVA += -beta_2 * term;
}
dVA = dVA*f_c_ij + df_c_ij*VA; VA *= f_c_ij;
del[0] = delx;
del[1] = dely;
del[2] = delz;
Bij = bondorder(i,j,del,rijmag,VA,f,vflag_atom);
dVAdi = Bij*dVA;
fpair = -(dVRdi-dVAdi) / rijmag;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
double evdwl=0.0;
if (eflag) evdwl = VR - Bij*VA;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
void PairLCBOP::FLR(int eflag, int )
{
int i,j,jj,ii;
tagint itag,jtag;
double delx,dely,delz,fpair,xtmp,ytmp,ztmp;
double r_sq,rijmag,f_c_ij,df_c_ij;
double V,dVdi;
double **x = atom->x;
double **f = atom->f;
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
int inum = list->inum;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
int *neighs = firstneigh[i];
for (jj = 0; jj < numneigh[i]; jj++) {
j = neighs[jj];
j &= NEIGHMASK;
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
r_sq = delx*delx + dely*dely + delz*delz;
rijmag = sqrt(r_sq);
f_c_ij = 1-f_c( rijmag,r_1,r_2,&df_c_ij );
df_c_ij = -df_c_ij;
f_c_ij *= f_c_LR( rijmag, r_1_LR, r_2_LR, &df_c_ij );
if (f_c_ij <= TOL) continue;
V = dVdi = 0;
if (rijmag<r_0) {
double exp_part = exp( -lambda_1*(rijmag-r_0) );
V = eps_1*( exp_part*exp_part - 2*exp_part) + v_1;
dVdi = 2*eps_1*lambda_1*exp_part*( 1-exp_part );
} else {
double exp_part = exp( -lambda_2*(rijmag-r_0) );
V = eps_2*( exp_part*exp_part - 2*exp_part) + v_2;
dVdi = 2*eps_2*lambda_2*exp_part*( 1-exp_part );
}
dVdi = dVdi*f_c_ij + df_c_ij*V; V *= f_c_ij;
fpair = -dVdi / rijmag;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
double evdwl=0.0;
if (eflag) evdwl = V;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
void PairLCBOP::FNij( int i, int j, double factor, double **f, int vflag_atom ) {
int atomi = i;
int atomj = j;
int *SR_neighs = SR_firstneigh[i];
double **x = atom->x;
for( int k=0; k<SR_numneigh[i]; k++ ) {
int atomk = SR_neighs[k];
if (atomk != atomj) {
double rik[3];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
double riksq = (rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]);
if (riksq > r_1*r_1) { double rikmag = sqrt(riksq);
double df_c_ik;
f_c( rikmag, r_1, r_2, &df_c_ik );
double fpair = -factor*df_c_ik / rikmag;
f[atomi][0] += rik[0]*fpair;
f[atomi][1] += rik[1]*fpair;
f[atomi][2] += rik[2]*fpair;
f[atomk][0] -= rik[0]*fpair;
f[atomk][1] -= rik[1]*fpair;
f[atomk][2] -= rik[2]*fpair;
if (vflag_atom) v_tally2(atomi,atomk,fpair,rik);
}
}
}
}
void PairLCBOP::FMij( int i, int j, double factor, double **f, int vflag_atom ) {
int atomi = i;
int atomj = j;
int *SR_neighs = SR_firstneigh[i];
double **x = atom->x;
for( int k=0; k<SR_numneigh[i]; k++ ) {
int atomk = SR_neighs[k];
if (atomk != atomj) {
double rik[3];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
double rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
double df_c_ik;
double f_c_ik = f_c( rikmag, r_1, r_2, &df_c_ik );
double Nki = N[k]-(f_c_ik);
double dF=0;
double Fx = 1-f_c_LR(Nki, 2,3,&dF);
dF = -dF;
if (df_c_ik > TOL) {
double factor2 = factor*df_c_ik*Fx;
double fpair = -factor2 / rikmag;
f[atomi][0] += rik[0]*fpair;
f[atomi][1] += rik[1]*fpair;
f[atomi][2] += rik[2]*fpair;
f[atomk][0] -= rik[0]*fpair;
f[atomk][1] -= rik[1]*fpair;
f[atomk][2] -= rik[2]*fpair;
if (vflag_atom) v_tally2(atomi,atomk,fpair,rik);
}
if (dF > TOL) {
double factor2 = factor*f_c_ik*dF;
FNij( atomk, atomi, factor2, f, vflag_atom );
}
}
}
}
double PairLCBOP::bondorder(int i, int j, double rij[3],
double rijmag, double VA,
double **f, int vflag_atom)
{
double bij, bji;
{
double rji[3];
rji[0] = -rij[0]; rji[1] = -rij[1]; rji[2] = -rij[2];
bij = b(i,j,rij,rijmag,VA,f,vflag_atom);
bji = b(j,i,rji,rijmag,VA,f,vflag_atom);
}
double Fij_conj;
{
double dummy;
double df_c_ij;
double f_c_ij = f_c( rijmag, r_1, r_2, &df_c_ij );
double Nij = MIN( 3, N[i]-(f_c_ij) );
double Nji = MIN( 3, N[j]-(f_c_ij) );
double Mij = M[i] - f_c_ij*( 1-f_c(Nji, 2,3,&dummy) );
double Mji = M[j] - f_c_ij*( 1-f_c(Nij, 2,3,&dummy) );
Mij = MIN( Mij, 3 );
Mji = MIN( Mji, 3 );
double Nij_el, dNij_el_dNij, dNij_el_dMij;
double Nji_el, dNji_el_dNji, dNji_el_dMji;
{
double num_Nij_el = 4 - Mij;
double num_Nji_el = 4 - Mji;
double den_Nij_el = Nij + 1 - Mij;
double den_Nji_el = Nji + 1 - Mji;
Nij_el = num_Nij_el / den_Nij_el;
Nji_el = num_Nji_el / den_Nji_el;
dNij_el_dNij = -Nij_el/den_Nij_el;
dNji_el_dNji = -Nji_el/den_Nji_el;
dNij_el_dMij = ( -1 + Nij_el ) /den_Nij_el;
dNji_el_dMji = ( -1 + Nji_el ) /den_Nji_el;
}
double Nconj;
double dNconj_dNij;
double dNconj_dNji;
double dNconj_dNel;
{
double num_Nconj = ( Nij+1 )*( Nji+1 )*( Nij_el+Nji_el ) - 4*( Nij+Nji+2);
double den_Nconj = Nij*( 3-Nij )*( Nji+1 ) + Nji*( 3-Nji )*( Nij+1 ) + eps;
Nconj = num_Nconj / den_Nconj;
if (Nconj <= 0) {
Nconj = 0;
dNconj_dNij = 0;
dNconj_dNji = 0;
dNconj_dNel = 0;
} else if (Nconj >= 1) {
Nconj = 1;
dNconj_dNij = 0;
dNconj_dNji = 0;
dNconj_dNel = 0;
} else {
dNconj_dNij = (
( (Nji+1)*(Nij_el + Nji_el)-4)
- Nconj*( (Nji+1)*(3-2*Nij) + Nji*(3-Nji) )
) /den_Nconj;
dNconj_dNji = (
( (Nij+1)*(Nji_el + Nij_el)-4)
- Nconj*( (Nij+1)*(3-2*Nji) + Nij*(3-Nij) )
) /den_Nconj;
dNconj_dNel = (Nij+1)*(Nji+1) / den_Nconj;
}
}
double dF_dNij, dF_dNji, dF_dNconj;
Fij_conj = F_conj( Nij, Nji, Nconj, &dF_dNij, &dF_dNji, &dF_dNconj );
if (3-Nij > TOL) {
double factor = -VA*0.5*( dF_dNij + dF_dNconj*( dNconj_dNij + dNconj_dNel*dNij_el_dNij ) );
FNij( i, j, factor, f, vflag_atom );
}
if (3-Nji > TOL) {
double factor = -VA*0.5*( dF_dNji + dF_dNconj*( dNconj_dNji + dNconj_dNel*dNji_el_dNji ) );
FNij( j, i, factor, f, vflag_atom );
}
if (3-Mij > TOL) {
double factor = -VA*0.5*( dF_dNconj*dNconj_dNel*dNij_el_dMij );
FMij( i, j, factor, f, vflag_atom );
}
if (3-Mji > TOL) {
double factor = -VA*0.5*( dF_dNconj*dNconj_dNel*dNji_el_dMji );
FMij( j, i, factor, f, vflag_atom );
}
}
double Bij = 0.5*( bij + bji + Fij_conj );
return Bij;
}
double PairLCBOP::b(int i, int j, double rij[3],
double rijmag, double VA,
double **f, int vflag_atom) {
int *SR_neighs = SR_firstneigh[i];
double **x = atom->x;
int atomi = i;
int atomj = j;
double bij = 1.0;
for (int k = 0; k < SR_numneigh[i]; k++) {
int atomk = SR_neighs[k];
if (atomk != atomj) {
double rik[3];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
double rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
double delta_ijk = rijmag-rikmag;
double dummy;
double f_c_ik = f_c( rikmag, r_1, r_2, &dummy );
double cos_ijk = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2]))
/ (rijmag*rikmag);
cos_ijk = MIN(cos_ijk,1.0);
cos_ijk = MAX(cos_ijk,-1.0);
double G = gSpline(cos_ijk, &dummy);
double H = hSpline(delta_ijk, &dummy);
bij += (f_c_ik*G*H);
}
}
bij = pow( bij, -delta );
for (int k = 0; k < SR_numneigh[i]; k++) {
int atomk = SR_neighs[k];
if (atomk != atomj) {
double rik[3];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
double rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
double delta_ijk = rijmag-rikmag;
double df_c_ik;
double f_c_ik = f_c( rikmag, r_1, r_2, &df_c_ik );
double cos_ijk = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2]))
/ (rijmag*rikmag);
cos_ijk = MIN(cos_ijk,1.0);
cos_ijk = MAX(cos_ijk,-1.0);
double dcos_ijk_dri[3],dcos_ijk_drj[3],dcos_ijk_drk[3];
dcos_ijk_drj[0] = -rik[0] / (rijmag*rikmag)
+ cos_ijk * rij[0] / (rijmag*rijmag);
dcos_ijk_drj[1] = -rik[1] / (rijmag*rikmag)
+ cos_ijk * rij[1] / (rijmag*rijmag);
dcos_ijk_drj[2] = -rik[2] / (rijmag*rikmag)
+ cos_ijk * rij[2] / (rijmag*rijmag);
dcos_ijk_drk[0] = -rij[0] / (rijmag*rikmag)
+ cos_ijk * rik[0] / (rikmag*rikmag);
dcos_ijk_drk[1] = -rij[1] / (rijmag*rikmag)
+ cos_ijk * rik[1] / (rikmag*rikmag);
dcos_ijk_drk[2] = -rij[2] / (rijmag*rikmag)
+ cos_ijk * rik[2] / (rikmag*rikmag);
dcos_ijk_dri[0] = -dcos_ijk_drk[0] - dcos_ijk_drj[0];
dcos_ijk_dri[1] = -dcos_ijk_drk[1] - dcos_ijk_drj[1];
dcos_ijk_dri[2] = -dcos_ijk_drk[2] - dcos_ijk_drj[2];
double dG, dH;
double G = gSpline( cos_ijk, &dG );
double H = hSpline( delta_ijk, &dH );
double tmp = -VA*0.5*(-0.5*bij*bij*bij);
double fi[3], fj[3], fk[3];
double tmp2 = -tmp*df_c_ik*G*H/rikmag;
fi[0] = tmp2*rik[0];
fi[1] = tmp2*rik[1];
fi[2] = tmp2*rik[2];
fk[0] = -tmp2*rik[0];
fk[1] = -tmp2*rik[1];
fk[2] = -tmp2*rik[2];
tmp2 = -tmp*f_c_ik*dG*H;
fi[0] += tmp2*dcos_ijk_dri[0];
fi[1] += tmp2*dcos_ijk_dri[1];
fi[2] += tmp2*dcos_ijk_dri[2];
fj[0] = tmp2*dcos_ijk_drj[0];
fj[1] = tmp2*dcos_ijk_drj[1];
fj[2] = tmp2*dcos_ijk_drj[2];
fk[0] += tmp2*dcos_ijk_drk[0];
fk[1] += tmp2*dcos_ijk_drk[1];
fk[2] += tmp2*dcos_ijk_drk[2];
tmp2 = -tmp*f_c_ik*G*dH;
fi[0] += tmp2*( rij[0]/rijmag - rik[0]/rikmag );
fi[1] += tmp2*( rij[1]/rijmag - rik[1]/rikmag );
fi[2] += tmp2*( rij[2]/rijmag - rik[2]/rikmag );
fj[0] += tmp2*( -rij[0]/rijmag );
fj[1] += tmp2*( -rij[1]/rijmag );
fj[2] += tmp2*( -rij[2]/rijmag );
fk[0] += tmp2*( rik[0]/rikmag );
fk[1] += tmp2*( rik[1]/rikmag );
fk[2] += tmp2*( rik[2]/rikmag );
f[atomi][0] += fi[0]; f[atomi][1] += fi[1]; f[atomi][2] += fi[2];
f[atomj][0] += fj[0]; f[atomj][1] += fj[1]; f[atomj][2] += fj[2];
f[atomk][0] += fk[0]; f[atomk][1] += fk[1]; f[atomk][2] += fk[2];
if (vflag_atom) {
double rji[3], rki[3];
rji[0] = -rij[0]; rji[1] = -rij[1]; rji[2] = -rij[2];
rki[0] = -rik[0]; rki[1] = -rik[1]; rki[2] = -rik[2];
v_tally3(atomi,atomj,atomk,fj,fk,rji,rki);
}
}
}
return bij;
}
void PairLCBOP::g_decompose_x( double x, size_t *field_idx, double *offset ) {
size_t i=0;
while( i<(6-1) && !( x<gX[i+1] ) )
i++;
*field_idx = i;
*offset = ( x - gX[i] );
}
double PairLCBOP::gSpline( double x, double *dgdc ) {
size_t i;
double x_n;
g_decompose_x( x, &i, &x_n );
double sum = 0;
*dgdc = 0;
double pow_x_n = 1.0;
for( size_t j=0; j<5; j++ ) {
sum += gC[j][i]*pow_x_n;
*dgdc += gC[j+1][i]*(j+1)*pow_x_n;
pow_x_n *= x_n;
}
sum += gC[5][i]*pow_x_n;
return sum;
}
double PairLCBOP::hSpline( double x, double *dhdx ) {
if (x < -d) {
double z = kappa*( x+d );
double y = pow(z, 10.0);
double w = pow( 1+y, -0.1 );
*dhdx = kappa*L*w/(1+y);
return L*( 1 + z*w );
}
if (x > d) {
*dhdx = R_1;
return R_0 + R_1*( x-d );
}
double result = 1 + C_1*x;
*dhdx = C_1*result;
double pow_x = x*x;
result += 0.5*C_1*C_1*pow_x;
pow_x *= x; *dhdx += 4*C_4*pow_x;
pow_x *= x; result += C_4*pow_x;
pow_x *= x; *dhdx += 6*C_6*pow_x;
pow_x *= x; result += C_6*pow_x;
return result;
}
double PairLCBOP::F_conj( double N_ij, double N_ji, double N_conj_ij, double *dFN_ij, double *dFN_ji, double *dFN_ij_conj ) {
size_t N_ij_int = MIN( static_cast<size_t>( floor( N_ij ) ), 2 ); size_t N_ji_int = MIN( static_cast<size_t>( floor( N_ji ) ), 2 ); double x = N_ij - N_ij_int;
double y = N_ji - N_ji_int;
const TF_conj_field &f0 = F_conj_field[N_ij_int][N_ji_int][0];
const TF_conj_field &f1 = F_conj_field[N_ij_int][N_ji_int][1];
double F_0 = 0;
double F_1 = 0;
double dF_0_dx = 0, dF_0_dy = 0;
double dF_1_dx = 0, dF_1_dy = 0;
double l, r;
if (N_conj_ij < 1) {
l = (1-y)* (1-x); r = ( f0.f_00 + x* x* f0.f_x_10 + y* y* f0.f_y_01 ); F_0 += l*r; dF_0_dx += -(1-y)*r +l*2*x* f0.f_x_10; dF_0_dy += -(1-x)*r +l*2*y* f0.f_y_01;
l = (1-y)* x; r = ( f0.f_10 + (1-x)*(1-x)*f0.f_x_00 + y* y* f0.f_y_11 ); F_0 += l*r; dF_0_dx += (1-y)*r -l*2*(1-x)*f0.f_x_00; dF_0_dy += -x* r +l*2*y* f0.f_y_11;
l = y* (1-x); r = ( f0.f_01 + x* x* f0.f_x_11 + (1-y)*(1-y)*f0.f_y_00 ); F_0 += l*r; dF_0_dx += -y* r +l*2*x* f0.f_x_11; dF_0_dy += (1-x)*r -l*2*(1-y)*f0.f_y_00;
l = y* x; r = ( f0.f_11 + (1-x)*(1-x)*f0.f_x_01 + (1-y)*(1-y)*f0.f_y_10 ); F_0 += l*r; dF_0_dx += y* r -l*2*(1-x)*f0.f_x_01; dF_0_dy += x* r -l*2*(1-y)*f0.f_y_10;
}
if (N_conj_ij > 0) {
l = (1-y)* (1-x); r = ( f0.f_00 + x* x* f1.f_x_10 + y* y* f1.f_y_01 ); F_1 += l*r; dF_1_dx += -(1-y)*r +l*2*x* f1.f_x_10; dF_1_dy += -(1-x)*r +l*2*y* f1.f_y_01;
l = (1-y)* x; r = ( f1.f_10 + (1-x)*(1-x)*f1.f_x_00 + y* y* f1.f_y_11 ); F_1 += l*r; dF_1_dx += (1-y)*r -l*2*(1-x)*f1.f_x_00; dF_1_dy += -x* r +l*2*y* f1.f_y_11;
l = y* (1-x); r = ( f1.f_01 + x* x* f1.f_x_11 + (1-y)*(1-y)*f1.f_y_00 ); F_1 += l*r; dF_1_dx += -y* r +l*2*x* f1.f_x_11; dF_1_dy += (1-x)*r -l*2*(1-y)*f1.f_y_00;
l = y* x; r = ( f1.f_11 + (1-x)*(1-x)*f1.f_x_01 + (1-y)*(1-y)*f1.f_y_10 ); F_1 += l*r; dF_1_dx += y* r -l*2*(1-x)*f1.f_x_01; dF_1_dy += x* r -l*2*(1-y)*f1.f_y_10;
}
double result = (1-N_conj_ij)*F_0 + N_conj_ij*F_1;
*dFN_ij = (1-N_conj_ij)*dF_0_dx + N_conj_ij*dF_1_dx;
*dFN_ji = (1-N_conj_ij)*dF_0_dy + N_conj_ij*dF_1_dy;
*dFN_ij_conj = -F_0 + F_1;
return result;
}
void PairLCBOP::read_file(char *filename)
{
int i,k,l;
char s[MAXLINE];
MPI_Comm_rank(world,&me);
if (me == 0) {
FILE *fp = force->open_potential(filename);
if (fp == NULL) {
char str[128];
snprintf(str,128,"Cannot open LCBOP potential file %s",filename);
error->one(FLERR,str);
}
while (1) {
fgets(s,MAXLINE,fp);
if (s[0] != '#') break;
}
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&r_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&r_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&gamma_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&A);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&B_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&B_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&alpha);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&beta_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&beta_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&d);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&C_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&C_4);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&C_6);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&L);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&kappa);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&R_0);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&R_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&r_0);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&r_1_LR);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&r_2_LR);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&v_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&v_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&eps_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&eps_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&lambda_1);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&lambda_2);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&eps);
fgets(s,MAXLINE,fp); sscanf(s,"%lg",&delta);
while (1) {
fgets(s,MAXLINE,fp);
if (s[0] != '#') break;
}
for (k = 0; k < 2; k++) { for (l = 0; l < 3; l++) { for (i = 0; i < 4; i++) { fgets(s,MAXLINE,fp);
sscanf(s,"%lg %lg %lg %lg",
&F_conj_data[i][0][k][l],
&F_conj_data[i][1][k][l],
&F_conj_data[i][2][k][l],
&F_conj_data[i][3][k][l]);
}
while (1) { fgets(s,MAXLINE,fp); if (s[0] != '#') break; }
}
}
fgets(s,MAXLINE,fp);
sscanf( s,"%lg %lg %lg %lg %lg %lg",
&gX[0], &gX[1], &gX[2],
&gX[3], &gX[4], &gX[5] );
for (i = 0; i < 6; i++) { fgets(s,MAXLINE,fp);
sscanf( s,"%lg %lg %lg %lg %lg",
&gC[i][0], &gC[i][1], &gC[i][2],
&gC[i][3], &gC[i][4] );
}
fclose(fp);
}
MPI_Bcast(&r_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&r_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&gamma_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&A ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&B_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&B_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&beta_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&beta_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&d ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&C_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&C_4 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&C_6 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&L ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&kappa ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&R_0 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&R_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&r_0 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&r_1_LR ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&r_2_LR ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&v_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&v_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&eps_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&eps_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&lambda_1 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&lambda_2 ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&eps ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&delta ,1,MPI_DOUBLE,0,world);
MPI_Bcast(&gX[0] ,6,MPI_DOUBLE,0,world);
MPI_Bcast(&gC[0][0] ,(6-1)*(5+1),MPI_DOUBLE,0,world);
MPI_Bcast(&F_conj_data[0],6*4*4,MPI_DOUBLE,0,world);
}
void PairLCBOP::spline_init() {
for( size_t N_conj_ij=0; N_conj_ij<2; N_conj_ij++ ) for( size_t N_ij=0; N_ij<4-1; N_ij++ )
for( size_t N_ji=0; N_ji<4-1; N_ji++ ) {
TF_conj_field &field = F_conj_field[N_ij][N_ji][N_conj_ij];
field.f_00 = F_conj_data[N_ij ][N_ji ][N_conj_ij][0];
field.f_01 = F_conj_data[N_ij ][N_ji+1][N_conj_ij][0];
field.f_10 = F_conj_data[N_ij+1][N_ji ][N_conj_ij][0];
field.f_11 = F_conj_data[N_ij+1][N_ji+1][N_conj_ij][0];
field.f_x_00 = F_conj_data[N_ij ][N_ji ][N_conj_ij][1] - field.f_10 + field.f_00;
field.f_x_01 = F_conj_data[N_ij ][N_ji+1][N_conj_ij][1] - field.f_11 + field.f_01;
field.f_x_10 = -(F_conj_data[N_ij+1][N_ji ][N_conj_ij][1] - field.f_10 + field.f_00);
field.f_x_11 = -(F_conj_data[N_ij+1][N_ji+1][N_conj_ij][1] - field.f_11 + field.f_01);
field.f_y_00 = F_conj_data[N_ij ][N_ji ][N_conj_ij][2] - field.f_01 + field.f_00;
field.f_y_01 = -(F_conj_data[N_ij ][N_ji+1][N_conj_ij][2] - field.f_01 + field.f_00);
field.f_y_10 = F_conj_data[N_ij+1][N_ji ][N_conj_ij][2] - field.f_11 + field.f_10;
field.f_y_11 = -(F_conj_data[N_ij+1][N_ji+1][N_conj_ij][2] - field.f_11 + field.f_10);
}
}
double PairLCBOP::memory_usage()
{
double bytes = 0.0;
bytes += maxlocal * sizeof(int);
bytes += maxlocal * sizeof(int *);
for (int i = 0; i < comm->nthreads; i++)
bytes += ipage[i].size();
bytes += 3*maxlocal * sizeof(double);
return bytes;
}