1274 lines
41 KiB
C++
1274 lines
41 KiB
C++
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
http://lammps.sandia.gov, Sandia National Laboratories
|
|
Steve Plimpton, sjplimp@sandia.gov
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
|
certain rights in this software. This software is distributed under
|
|
the GNU General Public License.
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
------------------------------------------------------------------------- */
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Contributing author: Dominik Wójt (Wroclaw University of Technology)
|
|
based on pair_airebo by Ase Henry (MIT)
|
|
------------------------------------------------------------------------- */
|
|
|
|
#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"
|
|
#include "utils.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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
check if allocated, since class can be destructed when incomplete
|
|
------------------------------------------------------------------------- */
|
|
|
|
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();
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
allocate all arrays
|
|
------------------------------------------------------------------------- */
|
|
|
|
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];
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
global settings
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::settings(int narg, char **/*arg*/) {
|
|
if (narg != 0 ) error->all(FLERR,"Illegal pair_style command");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
set coeffs for one or more type pairs
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::coeff(int narg, char **arg)
|
|
{
|
|
if (!allocated) allocate();
|
|
|
|
if (narg != 3 + atom->ntypes)
|
|
error->all(FLERR,"Incorrect args for pair coefficients");
|
|
|
|
// insure I,J args are * *
|
|
|
|
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
|
|
error->all(FLERR,"Incorrect args for pair coefficients");
|
|
|
|
// read args that map atom types to C and NULL
|
|
// map[i] = which element (0 for C) the Ith atom type is, -1 if NULL
|
|
|
|
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 potential file and initialize fitting splines
|
|
|
|
read_file(arg[2]);
|
|
spline_init();
|
|
|
|
// clear setflag since coeff() called once with I,J = * *
|
|
|
|
int n = atom->ntypes;
|
|
for (int i = 1; i <= n; i++)
|
|
for (int j = i; j <= n; j++)
|
|
setflag[i][j] = 0;
|
|
|
|
// set setflag i,j for type pairs where both are mapped to elements
|
|
|
|
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");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
init specific to this pair style
|
|
------------------------------------------------------------------------- */
|
|
|
|
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");
|
|
|
|
// need a full neighbor list, including neighbors of ghosts
|
|
|
|
int irequest = neighbor->request(this,instance_me);
|
|
neighbor->requests[irequest]->half = 0;
|
|
neighbor->requests[irequest]->full = 1;
|
|
neighbor->requests[irequest]->ghost = 1;
|
|
|
|
// local SR neighbor list
|
|
// create pages if first time or if neighbor pgsize/oneatom has changed
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
init for one type pair i,j and corresponding j,i
|
|
------------------------------------------------------------------------- */
|
|
|
|
double PairLCBOP::init_one(int i, int j)
|
|
{
|
|
if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
|
|
|
|
// cut3rebo = 3 SR distances
|
|
|
|
cut3rebo = 3.0 * r_2;
|
|
|
|
// cutmax = furthest distance from an owned atom
|
|
// at which another atom will feel force, i.e. the ghost cutoff
|
|
// for SR term in potential:
|
|
// interaction = M-K-I-J-L-N with I = owned and J = ghost
|
|
// I to N is max distance = 3 SR distances
|
|
// for V_LR term in potential:
|
|
// r_2_LR
|
|
// cutghost = SR cutoff used in SR_neigh() for neighbors of ghosts
|
|
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create SR neighbor list from main neighbor list
|
|
SR neighbor list stores neighbors of ghost atoms
|
|
------------------------------------------------------------------------- */
|
|
|
|
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) { // ensure ther is enough space
|
|
maxlocal = atom->nmax; // for atoms and ghosts allocated
|
|
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;
|
|
|
|
// store all SR neighs of owned and ghost atoms
|
|
// scan full neighbor list of I
|
|
|
|
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");
|
|
}
|
|
|
|
// calculate M_i
|
|
|
|
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;
|
|
// F(xij) = 1-f_c_LR(Nji, 2,3,&dummy)
|
|
M[i] += f_c_ij * ( 1-f_c_LR(Nji, 2,3,&dS) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Short range forces and energy
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::FSR(int eflag, int /*vflag*/)
|
|
{
|
|
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;
|
|
|
|
// two-body interactions from SR neighbor list, skip half of them
|
|
|
|
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 -> VR * f_c_ij
|
|
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 -> VA * f_c_ij
|
|
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;
|
|
|
|
// F = (dVRdi+dVAdi)*(-grad rijmag)
|
|
// grad_i rijmag = \vec{rij} /rijmag
|
|
// grad_j rijmag = -\vec{rij} /rijmag
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
compute long range forces and energy
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::FLR(int eflag, int /*vflag*/)
|
|
{
|
|
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;
|
|
|
|
// two-body interactions from full neighbor list, skip half of them
|
|
|
|
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;
|
|
// derivative may be inherited from previous call, see f_c_LR definition
|
|
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 -> V * f_c_ij
|
|
V *= f_c_ij;
|
|
|
|
// F = (dVdi)*(-grad rijmag)
|
|
// grad_i rijmag = \vec{rij} /rijmag
|
|
// grad_j rijmag = -\vec{rij} /rijmag
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
forces for Nij and Mij
|
|
------------------------------------------------------------------------- */
|
|
|
|
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) { // && riksq < r_2*r_2, if second condition not fulfilled neighbor would not be in the list
|
|
double rikmag = sqrt(riksq);
|
|
double df_c_ik;
|
|
f_c( rikmag, r_1, r_2, &df_c_ik );
|
|
|
|
// F = factor*df_c_ik*(-grad rikmag)
|
|
// grad_i rikmag = \vec{rik} /rikmag
|
|
// grad_k rikmag = -\vec{rik} /rikmag
|
|
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 Mij = M[i] - f_c_ij*( 1-f_c(Nji, 2,3,&dummy) );
|
|
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;
|
|
// F = factor2*(-grad rikmag)
|
|
// grad_i rikmag = \vec{rik} /rikmag
|
|
// grad_k rikmag = -\vec{rik} /rikmag
|
|
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 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Bij function
|
|
------------------------------------------------------------------------- */
|
|
|
|
double PairLCBOP::bondorder(int i, int j, double rij[3],
|
|
double rijmag, double VA,
|
|
double **f, int vflag_atom)
|
|
{
|
|
|
|
double bij, bji;
|
|
/* 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;
|
|
/* F_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) );
|
|
|
|
// F(xij) = 1-f_c(Nji, 2,3,&dummy)
|
|
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 );
|
|
|
|
/*forces for Nij*/
|
|
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 );
|
|
}
|
|
/*forces for Nji*/
|
|
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 );
|
|
}
|
|
/*forces for Mij*/
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
bij function
|
|
------------------------------------------------------------------------- */
|
|
|
|
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;
|
|
|
|
//calculate bij magnitude
|
|
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 );
|
|
|
|
// bij forces
|
|
|
|
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;
|
|
// F = tmp*df_c_ik*G*H*(-grad rikmag)
|
|
// grad_i rikmag = \vec{rik} /rikmag
|
|
// grad_k rikmag = -\vec{rik} /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;
|
|
// F = tmp*f_c_ik*dG*H*(-grad cos_ijk)
|
|
// grad_i cos_ijk = dcos_ijk_dri
|
|
// grad_j cos_ijk = dcos_ijk_drj
|
|
// grad_k cos_ijk = dcos_ijk_drk
|
|
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;
|
|
// F = tmp*f_c_ik*G*dH*(-grad delta_ijk)
|
|
// grad_i delta_ijk = \vec{rij} /rijmag - \vec{rik} /rijmag
|
|
// grad_j delta_ijk = -\vec{rij} /rijmag
|
|
// grad_k delta_ijk = \vec{rik} /rikmag
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
spline interpolation for G
|
|
------------------------------------------------------------------------- */
|
|
|
|
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;// == x^3
|
|
*dhdx += 4*C_4*pow_x;
|
|
pow_x *= x;// == x^4
|
|
result += C_4*pow_x;
|
|
pow_x *= x;// == x^5
|
|
*dhdx += 6*C_6*pow_x;
|
|
pow_x *= x;// == x^5
|
|
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 ); // 2 is the highest number of field
|
|
size_t N_ji_int = MIN( static_cast<size_t>( floor( N_ji ) ), 2 ); // cast to suppress warning
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read LCBOP potential file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::read_file(char *filename)
|
|
{
|
|
int i,k,l;
|
|
char s[MAXLINE];
|
|
|
|
MPI_Comm_rank(world,&me);
|
|
|
|
// read file on proc 0
|
|
|
|
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);
|
|
}
|
|
|
|
// skip initial comment lines
|
|
|
|
while (1) {
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error);
|
|
if (s[0] != '#') break;
|
|
}
|
|
|
|
// read parameters
|
|
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&r_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&r_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&gamma_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&A);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&B_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&B_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&alpha);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&beta_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&beta_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&d);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&C_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&C_4);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&C_6);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&L);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&kappa);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&R_0);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&R_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&r_0);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&r_1_LR);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&r_2_LR);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&v_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&v_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&eps_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&eps_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&lambda_1);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&lambda_2);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&eps);
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); sscanf(s,"%lg",&delta);
|
|
|
|
while (1) {
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error);
|
|
if (s[0] != '#') break;
|
|
}
|
|
|
|
// F_conj spline
|
|
|
|
for (k = 0; k < 2; k++) { // 2 values of N_ij_conj
|
|
for (l = 0; l < 3; l++) { // 3 types of data: f, dfdx, dfdy
|
|
for (i = 0; i < 4; i++) { // 4x4 matrix
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error);
|
|
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) { utils::sfgets(FLERR,s,MAXLINE,fp,filename,error); if (s[0] != '#') break; }
|
|
}
|
|
}
|
|
|
|
// G spline
|
|
|
|
// x coordinates of mesh points
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error);
|
|
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++) { // for each power in polynomial
|
|
utils::sfgets(FLERR,s,MAXLINE,fp,filename,error);
|
|
sscanf( s,"%lg %lg %lg %lg %lg",
|
|
&gC[i][0], &gC[i][1], &gC[i][2],
|
|
&gC[i][3], &gC[i][4] );
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
// broadcast read-in and setup values
|
|
|
|
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);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
init coefficients for TF_conj
|
|
------------------------------------------------------------------------- */
|
|
|
|
void PairLCBOP::spline_init() {
|
|
for( size_t N_conj_ij=0; N_conj_ij<2; N_conj_ij++ ) // 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);
|
|
}
|
|
|
|
//some testing:
|
|
// std::ofstream file( "test.txt" );
|
|
// file << "gX:\n";
|
|
// file << gX[0] << " "
|
|
// << gX[1] << " "
|
|
// << gX[2] << " "
|
|
// << gX[3] << " "
|
|
// << gX[4] << " "
|
|
// << gX[5] << std::endl;
|
|
// file << "gC:\n";
|
|
// for( int i=0; i<6; i++ )
|
|
// file << gC[i][0] << " "
|
|
// << gC[i][1] << " "
|
|
// << gC[i][2] << " "
|
|
// << gC[i][3] << " "
|
|
// << gC[i][4] << std::endl;
|
|
// file << std::endl;
|
|
//
|
|
// file << "gamma_1 = " << gamma_1 << std::endl;
|
|
// file << "r_1 = " << r_1 << std::endl;
|
|
// file << "r_2 = " << r_2 << std::endl;
|
|
// file << "A = " << A << std::endl;
|
|
// file << "B_1 = " << B_1 << std::endl;
|
|
// file << "B_2 = " << B_2 << std::endl;
|
|
// file << "alpha = " << alpha << std::endl;
|
|
// file << "beta_1 = " << beta_1 << std::endl;
|
|
// file << "beta_2 = " << beta_2 << std::endl;
|
|
// file << "d = " << d << std::endl;
|
|
// file << "C_1 = " << C_1 << std::endl;
|
|
// file << "C_4 = " << C_4 << std::endl;
|
|
// file << "C_6 = " << C_6 << std::endl;
|
|
// file << "L = " << L << std::endl;
|
|
// file << "kappa = " << kappa << std::endl;
|
|
// file << "R_0 = " << R_0 << std::endl;
|
|
// file << "R_1 = " << R_1 << std::endl;
|
|
// file << "r_0 = " << r_0 << std::endl;
|
|
// file << "r_1_LR = " << r_1_LR << std::endl;
|
|
// file << "r_2_LR = " << r_2_LR << std::endl;
|
|
// file << "v_1 = " << v_1 << std::endl;
|
|
// file << "v_2 = " << v_2 << std::endl;
|
|
// file << "eps_1 = " << eps_1 << std::endl;
|
|
// file << "eps_2 = " << eps_2 << std::endl;
|
|
// file << "lambda_1 = " << lambda_1 << std::endl;
|
|
// file << "lambda_2 = " << lambda_2 << std::endl;
|
|
// file << "eps = " << eps << std::endl;
|
|
// file << "delta = " << delta << std::endl;
|
|
// file << "r_2_sq = " << r_2_sq << std::endl;
|
|
// file << std::endl;
|
|
//
|
|
//
|
|
// file << "gSpline:" << std::endl;
|
|
// double x_1 = 1, x_0 = -1;
|
|
// int n=1000;
|
|
// double dx = (x_1-x_0)/n;
|
|
// for( double x=x_0; x<=x_1+0.0001; x+=dx ) {
|
|
// double g, dg;
|
|
// g = gSpline(x, &dg);
|
|
// file << x << " " << g << " " << dg << std::endl;
|
|
// }
|
|
// file << std::endl;
|
|
//
|
|
// file << "hSpline:" << std::endl;
|
|
// double x_1 = 1, x_0 = -1;
|
|
// int n=1000;
|
|
// double dx = (x_1-x_0)/n;
|
|
// for( double x=x_0; x<=x_1+0.0001; x+=dx ) {
|
|
// double h, dh;
|
|
// h = hSpline(x, &dh);
|
|
// file << x << " " << h << " " << dh << std::endl;
|
|
// }
|
|
// file << std::endl;
|
|
//
|
|
//
|
|
// file << "f_c:" << std::endl;
|
|
// double x_1 = 4, x_0 = 0;
|
|
// int n=1000;
|
|
// double dx = (x_1-x_0)/n;
|
|
// for( double x=x_0; x<=x_1+0.0001; x+=dx ) {
|
|
// double f, df;
|
|
// f = f_c(x, r_1, r_2, &df);
|
|
// file << x << " " << f << " " << df << std::endl;
|
|
// }
|
|
// file << std::endl;
|
|
|
|
// file << "F_conj_data\n";
|
|
// for (int k = 0; k < 2; k++) { // 2 values of N_ij_conj
|
|
// for (int l = 0; l < 3; l++) { // 3 types of data: f, dfdx, dfdy
|
|
// for (int i = 0; i < 4; i++) { // 4x4 matrix
|
|
// file
|
|
// << 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] << std::endl;
|
|
// }
|
|
// file << std::endl;
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// file << "F_conj_0 ";
|
|
// double dummy;
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 )
|
|
// file << y << " ";
|
|
// file << std::endl;
|
|
// for( double x=0; x<=3.0+0.0001; x+=0.1 ){
|
|
// file << x << " ";
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 )
|
|
// file << F_conj( x, y, 0, &dummy, &dummy, &dummy ) << " ";
|
|
// file << std::endl;
|
|
// }
|
|
//
|
|
// file << "dF0_dx ";
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 )
|
|
// file << y << " ";
|
|
// file << std::endl;
|
|
// for( double x=0; x<=3.0+0.0001; x+=0.1 ){
|
|
// file << x << " ";
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 ) {
|
|
// double dF_dx;
|
|
// F_conj( x, y, 0, &dF_dx, &dummy, &dummy );
|
|
// file << dF_dx << " ";
|
|
// }
|
|
// file << std::endl;
|
|
// }
|
|
//
|
|
//
|
|
//
|
|
// file << "F_conj_1 ";
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 )
|
|
// file << y << " ";
|
|
// file << std::endl;
|
|
// for( double x=0; x<=3.0+0.0001; x+=0.1 ){
|
|
// file << x << " ";
|
|
// for( double y=0; y<=3.0+0.0001; y+=0.1 )
|
|
// file << F_conj( x, y, 0, &dummy, &dummy, &dummy ) << " ";
|
|
// file << std::endl;
|
|
// }
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
memory usage of local atom-based arrays
|
|
------------------------------------------------------------------------- */
|
|
|
|
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;
|
|
}
|