git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@64 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
#include "mpi.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "math.h"
|
||||
#include "pppm.h"
|
||||
#include "atom.h"
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "angle.h"
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Angle::Angle()
|
||||
{
|
||||
allocated = 0;
|
||||
PI = 4.0*atan(1.0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if all coeffs are set
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Angle::init()
|
||||
{
|
||||
if (!allocated) error->all("Angle coeffs are not set");
|
||||
for (int i = 1; i <= atom->nangletypes; i++)
|
||||
if (setflag[i] == 0) error->all("All angle coeffs are not set");
|
||||
}
|
||||
|
||||
@ -1,310 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "angle_charmm.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleCharmm::~AngleCharmm()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(theta0);
|
||||
memory->sfree(k_ub);
|
||||
memory->sfree(r_ub);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmm::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,i3,n,type,factor;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,rfactor,dtheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
|
||||
double delxUB,delyUB,delzUB,rsqUB,rUB,dr,rk,forceUB;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **anglelist = neighbor->anglelist;
|
||||
int nanglelist = neighbor->nanglelist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nanglelist; n++) {
|
||||
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
if (newton_bond) factor = 3;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
}
|
||||
rfactor = factor/3.0;
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// Urey-Bradley bond
|
||||
|
||||
delxUB = x[i3][0] - x[i1][0];
|
||||
delyUB = x[i3][1] - x[i1][1];
|
||||
delzUB = x[i3][2] - x[i1][2];
|
||||
domain->minimum_image(&delxUB,&delyUB,&delzUB);
|
||||
|
||||
rsqUB = delxUB*delxUB + delyUB*delyUB + delzUB*delzUB;
|
||||
rUB = sqrt(rsqUB);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// harmonic force & energy
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
tk = k[type] * dtheta;
|
||||
|
||||
if (eflag) energy += rfactor * tk*dtheta;
|
||||
|
||||
a = 2.0 * tk * s;
|
||||
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
vx1 = a11*delx1 + a12*delx2;
|
||||
vx2 = a22*delx2 + a12*delx1;
|
||||
vy1 = a11*dely1 + a12*dely2;
|
||||
vy2 = a22*dely2 + a12*dely1;
|
||||
vz1 = a11*delz1 + a12*delz2;
|
||||
vz2 = a22*delz2 + a12*delz1;
|
||||
|
||||
// Urey-Bradley force & energy
|
||||
|
||||
dr = rUB - r_ub[type];
|
||||
rk = k_ub[type] * dr;
|
||||
|
||||
if (rUB > 0.0) forceUB = -2.0*rk/rUB;
|
||||
else forceUB = 0.0;
|
||||
|
||||
if (eflag) energy += rfactor * rk*dr;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= vx1 + delxUB*forceUB;
|
||||
f[i1][1] -= vy1 + delyUB*forceUB;
|
||||
f[i1][2] -= vz1 + delzUB*forceUB;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += vx1 + vx2;
|
||||
f[i2][1] += vy1 + vy2;
|
||||
f[i2][2] += vz1 + vz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] -= vx2 - delxUB*forceUB;
|
||||
f[i3][1] -= vy2 - delyUB*forceUB;
|
||||
f[i3][2] -= vz2 - delzUB*forceUB;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (delx1*vx1 + delx2*vx2 - delxUB*delxUB*forceUB);
|
||||
virial[1] -= rfactor * (dely1*vy1 + dely2*vy2 - delyUB*delyUB*forceUB);
|
||||
virial[2] -= rfactor * (delz1*vz1 + delz2*vz2 - delzUB*delzUB*forceUB);
|
||||
virial[3] -= rfactor * (delx1*vy1 + delx2*vy2 - delxUB*delyUB*forceUB);
|
||||
virial[4] -= rfactor * (delx1*vz1 + delx2*vz2 - delxUB*delzUB*forceUB);
|
||||
virial[5] -= rfactor * (dely1*vz1 + dely2*vz2 - delyUB*delzUB*forceUB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmm::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nangletypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"angle:k");
|
||||
theta0 = (double *) memory->smalloc((n+1)*sizeof(double),"angle:theta0");
|
||||
k_ub = (double *) memory->smalloc((n+1)*sizeof(double),"angle:k_ub");
|
||||
r_ub = (double *) memory->smalloc((n+1)*sizeof(double),"angle:r_ub");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"angle:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmm::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this angle style");
|
||||
if (narg != 5) error->all("Incorrect args for angle coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double theta0_one = atof(arg[2]);
|
||||
double k_ub_one = atof(arg[3]);
|
||||
double r_ub_one = atof(arg[4]);
|
||||
|
||||
// convert theta0 from degrees to radians
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
theta0[i] = theta0_one/180.0 * PI;
|
||||
k_ub[i] = k_ub_one;
|
||||
r_ub[i] = r_ub_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for angle coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCharmm::equilibrium_angle(int i)
|
||||
{
|
||||
return theta0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmm::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
fwrite(&k_ub[1],sizeof(double),atom->nangletypes,fp);
|
||||
fwrite(&r_ub[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmm::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
fread(&k_ub[1],sizeof(double),atom->nangletypes,fp);
|
||||
fread(&r_ub[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&k_ub[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r_ub[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCharmm::single(int type, int i1, int i2, int i3, double rfactor)
|
||||
{
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
|
||||
|
||||
double delxUB = x[i3][0] - x[i1][0];
|
||||
double delyUB = x[i3][1] - x[i1][1];
|
||||
double delzUB = x[i3][2] - x[i1][2];
|
||||
domain->minimum_image(&delxUB,&delyUB,&delzUB);
|
||||
double rUB = sqrt(delxUB*delxUB + delyUB*delyUB + delzUB*delzUB);
|
||||
|
||||
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
double dtheta = acos(c) - theta0[type];
|
||||
double tk = k[type] * dtheta;
|
||||
double dr = rUB - r_ub[type];
|
||||
double rk = k_ub[type] * dr;
|
||||
|
||||
return (rfactor * (tk*dtheta + rk*dr));
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ANGLE_CHARMM_H
|
||||
#define ANGLE_CHARMM_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "angle.h"
|
||||
|
||||
class AngleCharmm : public Angle {
|
||||
public:
|
||||
AngleCharmm() {}
|
||||
~AngleCharmm();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
double equilibrium_angle(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
double single(int, int, int, int, double);
|
||||
|
||||
private:
|
||||
double *k,*theta0,*k_ub,*r_ub;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,241 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "angle_cosine.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleCosine::~AngleCosine()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosine::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,i3,n,type,factor;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,rfactor;
|
||||
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **anglelist = neighbor->anglelist;
|
||||
int nanglelist = neighbor->nanglelist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nanglelist; n++) {
|
||||
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
if (newton_bond) factor = 3;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
}
|
||||
rfactor = factor/3.0;
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (eflag) energy += rfactor * k[type]*(1.0+c);
|
||||
|
||||
a = -k[type];
|
||||
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
vx1 = a11*delx1 + a12*delx2;
|
||||
vx2 = a22*delx2 + a12*delx1;
|
||||
vy1 = a11*dely1 + a12*dely2;
|
||||
vy2 = a22*dely2 + a12*dely1;
|
||||
vz1 = a11*delz1 + a12*delz2;
|
||||
vz2 = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= vx1;
|
||||
f[i1][1] -= vy1;
|
||||
f[i1][2] -= vz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += vx1 + vx2;
|
||||
f[i2][1] += vy1 + vy2;
|
||||
f[i2][2] += vz1 + vz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] -= vx2;
|
||||
f[i3][1] -= vy2;
|
||||
f[i3][2] -= vz2;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (delx1*vx1 + delx2*vx2);
|
||||
virial[1] -= rfactor * (dely1*vy1 + dely2*vy2);
|
||||
virial[2] -= rfactor * (delz1*vz1 + delz2*vz2);
|
||||
virial[3] -= rfactor * (delx1*vy1 + delx2*vy2);
|
||||
virial[4] -= rfactor * (delx1*vz1 + delx2*vz2);
|
||||
virial[5] -= rfactor * (dely1*vz1 + dely2*vz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosine::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nangletypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"angle:k");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"angle:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosine::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this angle style");
|
||||
if (narg != 2) error->all("Incorrect args for angle coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for angle coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCosine::equilibrium_angle(int i)
|
||||
{
|
||||
return PI;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosine::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosine::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCosine::single(int type, int i1, int i2, int i3, double rfactor)
|
||||
{
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
|
||||
|
||||
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
return (rfactor * k[type]*(1.0+c));
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ANGLE_COSINE_H
|
||||
#define ANGLE_COSINE_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "angle.h"
|
||||
|
||||
class AngleCosine : public Angle {
|
||||
public:
|
||||
AngleCosine() {}
|
||||
~AngleCosine();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
double equilibrium_angle(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
double single(int, int, int, int, double);
|
||||
|
||||
private:
|
||||
double *k;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,264 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Naveen Michaud-Agrawal (Johns Hopkins U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "angle_cosine_squared.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineSquared::~AngleCosineSquared()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(theta0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquared::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,i3,n,type,factor;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,rfactor,dcostheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **anglelist = neighbor->anglelist;
|
||||
int nanglelist = neighbor->nanglelist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nanglelist; n++) {
|
||||
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
if (newton_bond) factor = 3;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
}
|
||||
rfactor = factor/3.0;
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
|
||||
dcostheta = c - cos(theta0[type]);
|
||||
tk = k[type] * dcostheta;
|
||||
|
||||
if (eflag) energy += rfactor * tk*dcostheta;
|
||||
|
||||
a = -2.0 * tk;
|
||||
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
vx1 = a11*delx1 + a12*delx2;
|
||||
vx2 = a22*delx2 + a12*delx1;
|
||||
vy1 = a11*dely1 + a12*dely2;
|
||||
vy2 = a22*dely2 + a12*dely1;
|
||||
vz1 = a11*delz1 + a12*delz2;
|
||||
vz2 = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= vx1;
|
||||
f[i1][1] -= vy1;
|
||||
f[i1][2] -= vz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += vx1 + vx2;
|
||||
f[i2][1] += vy1 + vy2;
|
||||
f[i2][2] += vz1 + vz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] -= vx2;
|
||||
f[i3][1] -= vy2;
|
||||
f[i3][2] -= vz2;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (delx1*vx1 + delx2*vx2);
|
||||
virial[1] -= rfactor * (dely1*vy1 + dely2*vy2);
|
||||
virial[2] -= rfactor * (delz1*vz1 + delz2*vz2);
|
||||
virial[3] -= rfactor * (delx1*vy1 + delx2*vy2);
|
||||
virial[4] -= rfactor * (delx1*vz1 + delx2*vz2);
|
||||
virial[5] -= rfactor * (dely1*vz1 + dely2*vz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquared::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nangletypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"angle:k");
|
||||
theta0 = (double *) memory->smalloc((n+1)*sizeof(double),"angle:theta0");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"angle:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more types
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquared::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this angle style");
|
||||
if (narg != 3) error->all("Incorrect args for angle coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double theta0_one = atof(arg[2]);
|
||||
|
||||
// convert theta0 from degrees to radians
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
theta0[i] = theta0_one/180.0 * PI;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for angle coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCosineSquared::equilibrium_angle(int i)
|
||||
{
|
||||
return theta0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquared::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquared::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleCosineSquared::single(int type, int i1, int i2, int i3,
|
||||
double rfactor)
|
||||
{
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
|
||||
|
||||
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
double dcostheta = c - cos(theta0[type]);
|
||||
double tk = k[type] * dcostheta;
|
||||
return (rfactor * tk*dcostheta);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ANGLE_COSINE_SQUARED_H
|
||||
#define ANGLE_COSINE_SQUARED_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "angle.h"
|
||||
|
||||
class AngleCosineSquared : public Angle {
|
||||
public:
|
||||
AngleCosineSquared() {}
|
||||
~AngleCosineSquared();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
double equilibrium_angle(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
double single(int, int, int, int, double);
|
||||
|
||||
private:
|
||||
double *k,*theta0;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,263 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "angle_harmonic.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleHarmonic::~AngleHarmonic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(theta0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonic::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,i3,n,type,factor;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,rfactor,dtheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **anglelist = neighbor->anglelist;
|
||||
int nanglelist = neighbor->nanglelist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nanglelist; n++) {
|
||||
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
if (newton_bond) factor = 3;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
}
|
||||
rfactor = factor/3.0;
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// force & energy
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
tk = k[type] * dtheta;
|
||||
|
||||
if (eflag) energy += rfactor * tk*dtheta;
|
||||
|
||||
a = 2.0 * tk * s;
|
||||
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
vx1 = a11*delx1 + a12*delx2;
|
||||
vx2 = a22*delx2 + a12*delx1;
|
||||
vy1 = a11*dely1 + a12*dely2;
|
||||
vy2 = a22*dely2 + a12*dely1;
|
||||
vz1 = a11*delz1 + a12*delz2;
|
||||
vz2 = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= vx1;
|
||||
f[i1][1] -= vy1;
|
||||
f[i1][2] -= vz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += vx1 + vx2;
|
||||
f[i2][1] += vy1 + vy2;
|
||||
f[i2][2] += vz1 + vz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] -= vx2;
|
||||
f[i3][1] -= vy2;
|
||||
f[i3][2] -= vz2;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (delx1*vx1 + delx2*vx2);
|
||||
virial[1] -= rfactor * (dely1*vy1 + dely2*vy2);
|
||||
virial[2] -= rfactor * (delz1*vz1 + delz2*vz2);
|
||||
virial[3] -= rfactor * (delx1*vy1 + delx2*vy2);
|
||||
virial[4] -= rfactor * (delx1*vz1 + delx2*vz2);
|
||||
virial[5] -= rfactor * (dely1*vz1 + dely2*vz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nangletypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"angle:k");
|
||||
theta0 = (double *) memory->smalloc((n+1)*sizeof(double),"angle:theta0");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"angle:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more types
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonic::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this angle style");
|
||||
if (narg != 3) error->all("Incorrect args for angle coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double theta0_one = atof(arg[2]);
|
||||
|
||||
// convert theta0 from degrees to radians
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
theta0[i] = theta0_one/180.0 * PI;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for angle coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleHarmonic::equilibrium_angle(int i)
|
||||
{
|
||||
return theta0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleHarmonic::single(int type, int i1, int i2, int i3, double rfactor)
|
||||
{
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[i1][0] - x[i2][0];
|
||||
double dely1 = x[i1][1] - x[i2][1];
|
||||
double delz1 = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
|
||||
|
||||
double delx2 = x[i3][0] - x[i2][0];
|
||||
double dely2 = x[i3][1] - x[i2][1];
|
||||
double delz2 = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
|
||||
|
||||
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
double dtheta = acos(c) - theta0[type];
|
||||
double tk = k[type] * dtheta;
|
||||
return (rfactor * tk*dtheta);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ANGLE_HARMONIC_H
|
||||
#define ANGLE_HARMONIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "angle.h"
|
||||
|
||||
class AngleHarmonic : public Angle {
|
||||
public:
|
||||
AngleHarmonic() {}
|
||||
~AngleHarmonic();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
double equilibrium_angle(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
double single(int, int, int, int, double);
|
||||
|
||||
private:
|
||||
double *k,*theta0;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,262 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "angle_hybrid.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define EXTRA 1000
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set all global defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleHybrid::AngleHybrid()
|
||||
{
|
||||
nstyles = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
AngleHybrid::~AngleHybrid()
|
||||
{
|
||||
if (nstyles) {
|
||||
for (int i = 0; i < nstyles; i++) delete styles[i];
|
||||
delete [] styles;
|
||||
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
|
||||
delete [] keywords;
|
||||
}
|
||||
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(map);
|
||||
delete [] nanglelist;
|
||||
delete [] maxangle;
|
||||
for (int i = 0; i < nstyles; i++)
|
||||
memory->destroy_2d_int_array(anglelist[i]);
|
||||
delete [] anglelist;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n;
|
||||
|
||||
// save ptrs to original anglelist
|
||||
|
||||
int nanglelist_orig = neighbor->nanglelist;
|
||||
int **anglelist_orig = neighbor->anglelist;
|
||||
|
||||
// if this is re-neighbor step, create sub-style anglelists
|
||||
// nanglelist[] = length of each sub-style list
|
||||
// realloc sub-style anglelist if necessary
|
||||
// load sub-style anglelist with 4 values from original anglelist
|
||||
|
||||
if (neighbor->ago == 0) {
|
||||
for (m = 0; m < nstyles; m++) nanglelist[m] = 0;
|
||||
for (i = 0; i < nanglelist_orig; i++)
|
||||
nanglelist[map[anglelist_orig[i][3]]]++;
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (nanglelist[m] > maxangle[m]) {
|
||||
memory->destroy_2d_int_array(anglelist[m]);
|
||||
maxangle[m] = nanglelist[m] + EXTRA;
|
||||
anglelist[m] = (int **)
|
||||
memory->create_2d_int_array(maxangle[m],4,"angle_hybrid:anglelist");
|
||||
}
|
||||
nanglelist[m] = 0;
|
||||
}
|
||||
for (i = 0; i < nanglelist_orig; i++) {
|
||||
m = map[anglelist_orig[i][3]];
|
||||
n = nanglelist[m];
|
||||
anglelist[m][n][0] = anglelist_orig[i][0];
|
||||
anglelist[m][n][1] = anglelist_orig[i][1];
|
||||
anglelist[m][n][2] = anglelist_orig[i][2];
|
||||
anglelist[m][n][3] = anglelist_orig[i][3];
|
||||
nanglelist[m]++;
|
||||
}
|
||||
}
|
||||
|
||||
// call each sub-style's compute function
|
||||
// must set neighbor->anglelist to sub-style anglelist before call
|
||||
// accumulate sub-style energy,virial in hybrid's energy,virial
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (styles[m] == NULL) continue;
|
||||
neighbor->nanglelist = nanglelist[m];
|
||||
neighbor->anglelist = anglelist[m];
|
||||
styles[m]->compute(eflag,vflag);
|
||||
if (eflag) energy += styles[m]->energy;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
|
||||
}
|
||||
|
||||
// restore ptrs to original anglelist
|
||||
|
||||
neighbor->nanglelist = nanglelist_orig;
|
||||
neighbor->anglelist = anglelist_orig;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nangletypes;
|
||||
|
||||
map = (int *) memory->smalloc((n+1)*sizeof(int),"angle:map");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"angle:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
|
||||
nanglelist = new int[nstyles];
|
||||
maxangle = new int[nstyles];
|
||||
anglelist = new int**[nstyles];
|
||||
for (int m = 0; m < nstyles; m++) maxangle[m] = 0;
|
||||
for (int m = 0; m < nstyles; m++) anglelist[m] = NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create one angle style for each arg in list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::settings(int narg, char **arg)
|
||||
{
|
||||
nstyles = narg;
|
||||
styles = new Angle*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
for (int i = 0; i < m; i++)
|
||||
if (strcmp(arg[m],arg[i]) == 0)
|
||||
error->all("Angle style hybrid cannot use same angle style twice");
|
||||
if (strcmp(arg[m],"hybrid") == 0)
|
||||
error->all("Angle style hybrid cannot have hybrid as an argument");
|
||||
styles[m] = force->new_angle(arg[m]);
|
||||
keywords[m] = new char[strlen(arg[m])+1];
|
||||
strcpy(keywords[m],arg[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||
|
||||
// 2nd arg = angle style name (harmonic, etc)
|
||||
|
||||
int m;
|
||||
for (m = 0; m < nstyles; m++)
|
||||
if (strcmp(arg[1],keywords[m]) == 0) break;
|
||||
if (m == nstyles) error->all("Angle coeff for hybrid has invalid style");
|
||||
|
||||
// set low-level coefficients for each angletype
|
||||
// replace 2nd arg with i, call coeff() with no 1st arg
|
||||
// if sub-style is NULL for "none", still set setflag
|
||||
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
sprintf(arg[1],"%d",i);
|
||||
map[i] = m;
|
||||
if (styles[m]) styles[m]->coeff(which,narg-1,&arg[1]);
|
||||
setflag[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return an equilbrium angle length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double AngleHybrid::equilibrium_angle(int i)
|
||||
{
|
||||
return styles[map[i]]->equilibrium_angle(i);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&nstyles,sizeof(int),1,fp);
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
n = strlen(keywords[m]) + 1;
|
||||
fwrite(&n,sizeof(int),1,fp);
|
||||
fwrite(keywords[m],sizeof(char),n,fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AngleHybrid::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
int me = comm->me;
|
||||
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
|
||||
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
|
||||
styles = new Angle*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
if (me == 0) fread(&n,sizeof(int),1,fp);
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
keywords[m] = new char[n];
|
||||
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
|
||||
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
|
||||
styles[m] = force->new_angle(keywords[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double AngleHybrid::single(int type, int i1, int i2, int i3, double rfactor)
|
||||
{
|
||||
if (styles[map[type]])
|
||||
return styles[map[type]]->single(type,i1,i2,i3,rfactor);
|
||||
else return 0.0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AngleHybrid::memory_usage()
|
||||
{
|
||||
int bytes = 0;
|
||||
for (int m = 0; m < nstyles; m++) bytes += maxangle[m]*4 * sizeof(int);
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) bytes += styles[m]->memory_usage();
|
||||
return bytes;
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ANGLE_HYBRID_H
|
||||
#define ANGLE_HYBRID_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "angle.h"
|
||||
|
||||
class AngleHybrid : public Angle {
|
||||
public:
|
||||
AngleHybrid();
|
||||
~AngleHybrid();
|
||||
void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, int, char **);
|
||||
double equilibrium_angle(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
double single(int, int, int, int, double);
|
||||
int memory_usage();
|
||||
|
||||
private:
|
||||
int nstyles; // # of different angle styles
|
||||
Angle **styles; // class list for each Angle style
|
||||
char **keywords; // keyword for each Angle style
|
||||
int *map; // which style each angle type points to
|
||||
|
||||
int *nanglelist; // # of angles in sub-style anglelists
|
||||
int *maxangle; // max # of angles sub-style lists can store
|
||||
int ***anglelist; // anglelist for each sub-style
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,290 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "atom_angle.h"
|
||||
#include "domain.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomAngle::AtomAngle(int narg, char **arg) : Atom(narg, arg) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::copy(int i, int j)
|
||||
{
|
||||
int k;
|
||||
|
||||
tag[j] = tag[i];
|
||||
type[j] = type[i];
|
||||
mask[j] = mask[i];
|
||||
image[j] = image[i];
|
||||
x[j][0] = x[i][0];
|
||||
x[j][1] = x[i][1];
|
||||
x[j][2] = x[i][2];
|
||||
v[j][0] = v[i][0];
|
||||
v[j][1] = v[i][1];
|
||||
v[j][2] = v[i][2];
|
||||
|
||||
molecule[j] = molecule[i];
|
||||
num_bond[j] = num_bond[i];
|
||||
num_angle[j] = num_angle[i];
|
||||
nspecial[j][0] = nspecial[i][0];
|
||||
nspecial[j][1] = nspecial[i][1];
|
||||
nspecial[j][2] = nspecial[i][2];
|
||||
|
||||
for (k = 0; k < num_bond[j]; k++) {
|
||||
bond_type[j][k] = bond_type[i][k];
|
||||
bond_atom[j][k] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_angle[j]; k++) {
|
||||
angle_type[j][k] = angle_type[i][k];
|
||||
angle_atom1[j][k] = angle_atom1[i][k];
|
||||
angle_atom2[j][k] = angle_atom2[i][k];
|
||||
angle_atom3[j][k] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
modify->fix[extra_grow[iextra]]->copy_arrays(i,j);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::pack_comm(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::pack_reverse(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = f[i][0];
|
||||
buf[m++] = f[i][1];
|
||||
buf[m++] = f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::unpack_reverse(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
f[j][0] += buf[m++];
|
||||
f[j][1] += buf[m++];
|
||||
f[j][2] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::pack_border(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomAngle::unpack_border(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = static_cast<int> (buf[m++]);
|
||||
type[i] = static_cast<int> (buf[m++]);
|
||||
mask[i] = static_cast<int> (buf[m++]);
|
||||
molecule[i] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack all atom quantities for shipping to another proc
|
||||
xyz must be 1st 3 values, so that comm::exchange can test on them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomAngle::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int k;
|
||||
|
||||
int m = 1;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = tag[i];
|
||||
buf[m++] = type[i];
|
||||
buf[m++] = mask[i];
|
||||
buf[m++] = image[i];
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
|
||||
buf[m++] = molecule[i];
|
||||
|
||||
buf[m++] = num_bond[i];
|
||||
for (k = 0; k < num_bond[i]; k++) {
|
||||
buf[m++] = bond_type[i][k];
|
||||
buf[m++] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_angle[i];
|
||||
for (k = 0; k < num_angle[i]; k++) {
|
||||
buf[m++] = angle_type[i][k];
|
||||
buf[m++] = angle_atom1[i][k];
|
||||
buf[m++] = angle_atom2[i][k];
|
||||
buf[m++] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = nspecial[i][0];
|
||||
buf[m++] = nspecial[i][1];
|
||||
buf[m++] = nspecial[i][2];
|
||||
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->pack_exchange(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomAngle::unpack_exchange(double *buf)
|
||||
{
|
||||
int k;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = static_cast<int> (buf[m++]);
|
||||
type[nlocal] = static_cast<int> (buf[m++]);
|
||||
mask[nlocal] = static_cast<int> (buf[m++]);
|
||||
image[nlocal] = static_cast<int> (buf[m++]);
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
|
||||
molecule[nlocal] = static_cast<int> (buf[m++]);
|
||||
|
||||
num_bond[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_bond[nlocal]; k++) {
|
||||
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_angle[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_angle[nlocal]; k++) {
|
||||
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < nspecial[nlocal][2]; k++)
|
||||
special[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->unpack_exchange(nlocal,&buf[m]);
|
||||
|
||||
nlocal++;
|
||||
return m;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ATOM_ANGLE_H
|
||||
#define ATOM_ANGLE_H
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
class AtomAngle : public Atom {
|
||||
public:
|
||||
AtomAngle(int, char **);
|
||||
~AtomAngle() {}
|
||||
void copy(int, int);
|
||||
void pack_comm(int, int *, double *, int *);
|
||||
void unpack_comm(int, int, double *);
|
||||
void pack_reverse(int, int, double *);
|
||||
void unpack_reverse(int, int *, double *);
|
||||
void pack_border(int, int *, double *, int *);
|
||||
void unpack_border(int, int, double *);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,266 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "atom_bond.h"
|
||||
#include "domain.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomBond::AtomBond(int narg, char **arg) : Atom(narg, arg) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::copy(int i, int j)
|
||||
{
|
||||
int k;
|
||||
|
||||
tag[j] = tag[i];
|
||||
type[j] = type[i];
|
||||
mask[j] = mask[i];
|
||||
image[j] = image[i];
|
||||
x[j][0] = x[i][0];
|
||||
x[j][1] = x[i][1];
|
||||
x[j][2] = x[i][2];
|
||||
v[j][0] = v[i][0];
|
||||
v[j][1] = v[i][1];
|
||||
v[j][2] = v[i][2];
|
||||
|
||||
molecule[j] = molecule[i];
|
||||
num_bond[j] = num_bond[i];
|
||||
nspecial[j][0] = nspecial[i][0];
|
||||
nspecial[j][1] = nspecial[i][1];
|
||||
nspecial[j][2] = nspecial[i][2];
|
||||
|
||||
for (k = 0; k < num_bond[j]; k++) {
|
||||
bond_type[j][k] = bond_type[i][k];
|
||||
bond_atom[j][k] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
modify->fix[extra_grow[iextra]]->copy_arrays(i,j);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::pack_comm(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::pack_reverse(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = f[i][0];
|
||||
buf[m++] = f[i][1];
|
||||
buf[m++] = f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::unpack_reverse(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
f[j][0] += buf[m++];
|
||||
f[j][1] += buf[m++];
|
||||
f[j][2] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::pack_border(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomBond::unpack_border(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = static_cast<int> (buf[m++]);
|
||||
type[i] = static_cast<int> (buf[m++]);
|
||||
mask[i] = static_cast<int> (buf[m++]);
|
||||
molecule[i] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack all atom quantities for shipping to another proc
|
||||
xyz must be 1st 3 values, so that comm::exchange can test on them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomBond::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int k;
|
||||
|
||||
int m = 1;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = tag[i];
|
||||
buf[m++] = type[i];
|
||||
buf[m++] = mask[i];
|
||||
buf[m++] = image[i];
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
|
||||
buf[m++] = molecule[i];
|
||||
|
||||
buf[m++] = num_bond[i];
|
||||
for (k = 0; k < num_bond[i]; k++) {
|
||||
buf[m++] = bond_type[i][k];
|
||||
buf[m++] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = nspecial[i][0];
|
||||
buf[m++] = nspecial[i][1];
|
||||
buf[m++] = nspecial[i][2];
|
||||
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->pack_exchange(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomBond::unpack_exchange(double *buf)
|
||||
{
|
||||
int k;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = static_cast<int> (buf[m++]);
|
||||
type[nlocal] = static_cast<int> (buf[m++]);
|
||||
mask[nlocal] = static_cast<int> (buf[m++]);
|
||||
image[nlocal] = static_cast<int> (buf[m++]);
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
|
||||
molecule[nlocal] = static_cast<int> (buf[m++]);
|
||||
|
||||
num_bond[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_bond[nlocal]; k++) {
|
||||
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < nspecial[nlocal][2]; k++)
|
||||
special[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->unpack_exchange(nlocal,&buf[m]);
|
||||
|
||||
nlocal++;
|
||||
return m;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ATOM_BOND_H
|
||||
#define ATOM_BOND_H
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
class AtomBond : public Atom {
|
||||
public:
|
||||
AtomBond(int, char **);
|
||||
~AtomBond() {}
|
||||
void copy(int, int);
|
||||
void pack_comm(int, int *, double *, int *);
|
||||
void unpack_comm(int, int, double *);
|
||||
void pack_reverse(int, int, double *);
|
||||
void unpack_reverse(int, int *, double *);
|
||||
void pack_border(int, int *, double *, int *);
|
||||
void unpack_border(int, int, double *);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,353 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "atom_full.h"
|
||||
#include "domain.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomFull::AtomFull(int narg, char **arg) : Atom(narg, arg) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::copy(int i, int j)
|
||||
{
|
||||
int k;
|
||||
|
||||
tag[j] = tag[i];
|
||||
type[j] = type[i];
|
||||
mask[j] = mask[i];
|
||||
image[j] = image[i];
|
||||
x[j][0] = x[i][0];
|
||||
x[j][1] = x[i][1];
|
||||
x[j][2] = x[i][2];
|
||||
v[j][0] = v[i][0];
|
||||
v[j][1] = v[i][1];
|
||||
v[j][2] = v[i][2];
|
||||
|
||||
q[j] = q[i];
|
||||
|
||||
molecule[j] = molecule[i];
|
||||
num_bond[j] = num_bond[i];
|
||||
num_angle[j] = num_angle[i];
|
||||
num_dihedral[j] = num_dihedral[i];
|
||||
num_improper[j] = num_improper[i];
|
||||
nspecial[j][0] = nspecial[i][0];
|
||||
nspecial[j][1] = nspecial[i][1];
|
||||
nspecial[j][2] = nspecial[i][2];
|
||||
|
||||
for (k = 0; k < num_bond[j]; k++) {
|
||||
bond_type[j][k] = bond_type[i][k];
|
||||
bond_atom[j][k] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_angle[j]; k++) {
|
||||
angle_type[j][k] = angle_type[i][k];
|
||||
angle_atom1[j][k] = angle_atom1[i][k];
|
||||
angle_atom2[j][k] = angle_atom2[i][k];
|
||||
angle_atom3[j][k] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_dihedral[j]; k++) {
|
||||
dihedral_type[j][k] = dihedral_type[i][k];
|
||||
dihedral_atom1[j][k] = dihedral_atom1[i][k];
|
||||
dihedral_atom2[j][k] = dihedral_atom2[i][k];
|
||||
dihedral_atom3[j][k] = dihedral_atom3[i][k];
|
||||
dihedral_atom4[j][k] = dihedral_atom4[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_improper[j]; k++) {
|
||||
improper_type[j][k] = improper_type[i][k];
|
||||
improper_atom1[j][k] = improper_atom1[i][k];
|
||||
improper_atom2[j][k] = improper_atom2[i][k];
|
||||
improper_atom3[j][k] = improper_atom3[i][k];
|
||||
improper_atom4[j][k] = improper_atom4[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
modify->fix[extra_grow[iextra]]->copy_arrays(i,j);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::pack_comm(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::pack_reverse(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = f[i][0];
|
||||
buf[m++] = f[i][1];
|
||||
buf[m++] = f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::unpack_reverse(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
f[j][0] += buf[m++];
|
||||
f[j][1] += buf[m++];
|
||||
f[j][2] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::pack_border(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = q[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = q[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomFull::unpack_border(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = static_cast<int> (buf[m++]);
|
||||
type[i] = static_cast<int> (buf[m++]);
|
||||
mask[i] = static_cast<int> (buf[m++]);
|
||||
q[i] = buf[m++];
|
||||
molecule[i] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack all atom quantities for shipping to another proc
|
||||
xyz must be 1st 3 values, so that comm::exchange can test on them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomFull::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int k;
|
||||
|
||||
int m = 1;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = tag[i];
|
||||
buf[m++] = type[i];
|
||||
buf[m++] = mask[i];
|
||||
buf[m++] = image[i];
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
|
||||
buf[m++] = q[i];
|
||||
|
||||
buf[m++] = molecule[i];
|
||||
|
||||
buf[m++] = num_bond[i];
|
||||
for (k = 0; k < num_bond[i]; k++) {
|
||||
buf[m++] = bond_type[i][k];
|
||||
buf[m++] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_angle[i];
|
||||
for (k = 0; k < num_angle[i]; k++) {
|
||||
buf[m++] = angle_type[i][k];
|
||||
buf[m++] = angle_atom1[i][k];
|
||||
buf[m++] = angle_atom2[i][k];
|
||||
buf[m++] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_dihedral[i];
|
||||
for (k = 0; k < num_dihedral[i]; k++) {
|
||||
buf[m++] = dihedral_type[i][k];
|
||||
buf[m++] = dihedral_atom1[i][k];
|
||||
buf[m++] = dihedral_atom2[i][k];
|
||||
buf[m++] = dihedral_atom3[i][k];
|
||||
buf[m++] = dihedral_atom4[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_improper[i];
|
||||
for (k = 0; k < num_improper[i]; k++) {
|
||||
buf[m++] = improper_type[i][k];
|
||||
buf[m++] = improper_atom1[i][k];
|
||||
buf[m++] = improper_atom2[i][k];
|
||||
buf[m++] = improper_atom3[i][k];
|
||||
buf[m++] = improper_atom4[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = nspecial[i][0];
|
||||
buf[m++] = nspecial[i][1];
|
||||
buf[m++] = nspecial[i][2];
|
||||
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->pack_exchange(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomFull::unpack_exchange(double *buf)
|
||||
{
|
||||
int k;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = static_cast<int> (buf[m++]);
|
||||
type[nlocal] = static_cast<int> (buf[m++]);
|
||||
mask[nlocal] = static_cast<int> (buf[m++]);
|
||||
image[nlocal] = static_cast<int> (buf[m++]);
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
|
||||
q[nlocal] = buf[m++];
|
||||
|
||||
molecule[nlocal] = static_cast<int> (buf[m++]);
|
||||
|
||||
num_bond[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_bond[nlocal]; k++) {
|
||||
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_angle[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_angle[nlocal]; k++) {
|
||||
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_dihedral[nlocal]; k++) {
|
||||
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_improper[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_improper[nlocal]; k++) {
|
||||
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < nspecial[nlocal][2]; k++)
|
||||
special[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->unpack_exchange(nlocal,&buf[m]);
|
||||
|
||||
nlocal++;
|
||||
return m;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ATOM_FULL_H
|
||||
#define ATOM_FULL_H
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
class AtomFull : public Atom {
|
||||
public:
|
||||
AtomFull(int, char **);
|
||||
~AtomFull() {}
|
||||
void copy(int, int);
|
||||
void pack_comm(int, int *, double *, int *);
|
||||
void unpack_comm(int, int, double *);
|
||||
void pack_reverse(int, int, double *);
|
||||
void unpack_reverse(int, int *, double *);
|
||||
void pack_border(int, int *, double *, int *);
|
||||
void unpack_border(int, int, double *);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,344 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "atom_molecular.h"
|
||||
#include "domain.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomMolecular::AtomMolecular(int narg, char **arg) : Atom(narg, arg) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::copy(int i, int j)
|
||||
{
|
||||
int k;
|
||||
|
||||
tag[j] = tag[i];
|
||||
type[j] = type[i];
|
||||
mask[j] = mask[i];
|
||||
image[j] = image[i];
|
||||
x[j][0] = x[i][0];
|
||||
x[j][1] = x[i][1];
|
||||
x[j][2] = x[i][2];
|
||||
v[j][0] = v[i][0];
|
||||
v[j][1] = v[i][1];
|
||||
v[j][2] = v[i][2];
|
||||
|
||||
molecule[j] = molecule[i];
|
||||
num_bond[j] = num_bond[i];
|
||||
num_angle[j] = num_angle[i];
|
||||
num_dihedral[j] = num_dihedral[i];
|
||||
num_improper[j] = num_improper[i];
|
||||
nspecial[j][0] = nspecial[i][0];
|
||||
nspecial[j][1] = nspecial[i][1];
|
||||
nspecial[j][2] = nspecial[i][2];
|
||||
|
||||
for (k = 0; k < num_bond[j]; k++) {
|
||||
bond_type[j][k] = bond_type[i][k];
|
||||
bond_atom[j][k] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_angle[j]; k++) {
|
||||
angle_type[j][k] = angle_type[i][k];
|
||||
angle_atom1[j][k] = angle_atom1[i][k];
|
||||
angle_atom2[j][k] = angle_atom2[i][k];
|
||||
angle_atom3[j][k] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_dihedral[j]; k++) {
|
||||
dihedral_type[j][k] = dihedral_type[i][k];
|
||||
dihedral_atom1[j][k] = dihedral_atom1[i][k];
|
||||
dihedral_atom2[j][k] = dihedral_atom2[i][k];
|
||||
dihedral_atom3[j][k] = dihedral_atom3[i][k];
|
||||
dihedral_atom4[j][k] = dihedral_atom4[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < num_improper[j]; k++) {
|
||||
improper_type[j][k] = improper_type[i][k];
|
||||
improper_atom1[j][k] = improper_atom1[i][k];
|
||||
improper_atom2[j][k] = improper_atom2[i][k];
|
||||
improper_atom3[j][k] = improper_atom3[i][k];
|
||||
improper_atom4[j][k] = improper_atom4[i][k];
|
||||
}
|
||||
|
||||
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
modify->fix[extra_grow[iextra]]->copy_arrays(i,j);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::pack_comm(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::pack_reverse(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = f[i][0];
|
||||
buf[m++] = f[i][1];
|
||||
buf[m++] = f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::unpack_reverse(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
f[j][0] += buf[m++];
|
||||
f[j][1] += buf[m++];
|
||||
f[j][2] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::pack_border(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flags[0] == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
} else {
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + pbc_flags[1]*xprd;
|
||||
buf[m++] = x[j][1] + pbc_flags[2]*yprd;
|
||||
buf[m++] = x[j][2] + pbc_flags[3]*zprd;
|
||||
buf[m++] = tag[j];
|
||||
buf[m++] = type[j];
|
||||
buf[m++] = mask[j];
|
||||
buf[m++] = molecule[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomMolecular::unpack_border(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = static_cast<int> (buf[m++]);
|
||||
type[i] = static_cast<int> (buf[m++]);
|
||||
mask[i] = static_cast<int> (buf[m++]);
|
||||
molecule[i] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack all atom quantities for shipping to another proc
|
||||
xyz must be 1st 3 values, so that comm::exchange can test on them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomMolecular::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int k;
|
||||
|
||||
int m = 1;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = tag[i];
|
||||
buf[m++] = type[i];
|
||||
buf[m++] = mask[i];
|
||||
buf[m++] = image[i];
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
|
||||
buf[m++] = molecule[i];
|
||||
|
||||
buf[m++] = num_bond[i];
|
||||
for (k = 0; k < num_bond[i]; k++) {
|
||||
buf[m++] = bond_type[i][k];
|
||||
buf[m++] = bond_atom[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_angle[i];
|
||||
for (k = 0; k < num_angle[i]; k++) {
|
||||
buf[m++] = angle_type[i][k];
|
||||
buf[m++] = angle_atom1[i][k];
|
||||
buf[m++] = angle_atom2[i][k];
|
||||
buf[m++] = angle_atom3[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_dihedral[i];
|
||||
for (k = 0; k < num_dihedral[i]; k++) {
|
||||
buf[m++] = dihedral_type[i][k];
|
||||
buf[m++] = dihedral_atom1[i][k];
|
||||
buf[m++] = dihedral_atom2[i][k];
|
||||
buf[m++] = dihedral_atom3[i][k];
|
||||
buf[m++] = dihedral_atom4[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = num_improper[i];
|
||||
for (k = 0; k < num_improper[i]; k++) {
|
||||
buf[m++] = improper_type[i][k];
|
||||
buf[m++] = improper_atom1[i][k];
|
||||
buf[m++] = improper_atom2[i][k];
|
||||
buf[m++] = improper_atom3[i][k];
|
||||
buf[m++] = improper_atom4[i][k];
|
||||
}
|
||||
|
||||
buf[m++] = nspecial[i][0];
|
||||
buf[m++] = nspecial[i][1];
|
||||
buf[m++] = nspecial[i][2];
|
||||
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->pack_exchange(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomMolecular::unpack_exchange(double *buf)
|
||||
{
|
||||
int k;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = static_cast<int> (buf[m++]);
|
||||
type[nlocal] = static_cast<int> (buf[m++]);
|
||||
mask[nlocal] = static_cast<int> (buf[m++]);
|
||||
image[nlocal] = static_cast<int> (buf[m++]);
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
|
||||
molecule[nlocal] = static_cast<int> (buf[m++]);
|
||||
|
||||
num_bond[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_bond[nlocal]; k++) {
|
||||
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_angle[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_angle[nlocal]; k++) {
|
||||
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_dihedral[nlocal]; k++) {
|
||||
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
num_improper[nlocal] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < num_improper[nlocal]; k++) {
|
||||
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
}
|
||||
|
||||
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
|
||||
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
|
||||
for (k = 0; k < nspecial[nlocal][2]; k++)
|
||||
special[nlocal][k] = static_cast<int> (buf[m++]);
|
||||
|
||||
if (nextra_grow)
|
||||
for (int iextra = 0; iextra < nextra_grow; iextra++)
|
||||
m += modify->fix[extra_grow[iextra]]->unpack_exchange(nlocal,&buf[m]);
|
||||
|
||||
nlocal++;
|
||||
return m;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef ATOM_MOLECULAR_H
|
||||
#define ATOM_MOLECULAR_H
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
class AtomMolecular : public Atom {
|
||||
public:
|
||||
AtomMolecular(int, char **);
|
||||
~AtomMolecular() {}
|
||||
void copy(int, int);
|
||||
void pack_comm(int, int *, double *, int *);
|
||||
void unpack_comm(int, int, double *);
|
||||
void pack_reverse(int, int, double *);
|
||||
void unpack_reverse(int, int *, double *);
|
||||
void pack_border(int, int *, double *, int *);
|
||||
void unpack_border(int, int, double *);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
40
src/bond.cpp
40
src/bond.cpp
@ -1,40 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "string.h"
|
||||
#include "bond.h"
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
set bond contribution to Vdwl energy to 0.0
|
||||
a particular bond style can override this
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
Bond::Bond()
|
||||
{
|
||||
allocated = 0;
|
||||
eng_vdwl = 0.0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if all coeffs are set
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Bond::init()
|
||||
{
|
||||
if (!allocated) error->all("Bond coeffs are not set");
|
||||
for (int i = 1; i <= atom->nbondtypes; i++)
|
||||
if (setflag[i] == 0) error->all("All bond coeffs are not set");
|
||||
init_style();
|
||||
}
|
||||
@ -1,272 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_fene.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondFENE::BondFENE()
|
||||
{
|
||||
TWO_1_3 = pow(2.0,(1.0/3.0));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondFENE::~BondFENE()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(r0);
|
||||
memory->sfree(epsilon);
|
||||
memory->sfree(sigma);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,type,factor;
|
||||
double delx,dely,delz,rsq,r0sq,rlogarg,fforce,sr2,sr6,rfactor;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5*factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
// force from log term
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r0sq = r0[type] * r0[type];
|
||||
rlogarg = 1.0 - rsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
sprintf(str,"FENE bond too long: %d %d %d %g",
|
||||
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
|
||||
error->warning(str);
|
||||
if (rlogarg <= -3.0) error->one("Bad FENE bond");
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fforce = -k[type]/rlogarg;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*epsilon[type]*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (eflag) {
|
||||
energy -= 0.5*rfactor * k[type]*r0sq*log(rlogarg);
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
energy += rfactor * (4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]);
|
||||
}
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor * delx*delx*fforce;
|
||||
virial[1] += rfactor * dely*dely*fforce;
|
||||
virial[2] += rfactor * delz*delz*fforce;
|
||||
virial[3] += rfactor * delx*dely*fforce;
|
||||
virial[4] += rfactor * delx*delz*fforce;
|
||||
virial[5] += rfactor * dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"bond:k");
|
||||
r0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:r0");
|
||||
epsilon = (double *) memory->smalloc((n+1)*sizeof(double),"bond:epsilon");
|
||||
sigma = (double *) memory->smalloc((n+1)*sizeof(double),"bond:sigma");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 5) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double r0_one = atof(arg[2]);
|
||||
double epsilon_one = atof(arg[3]);
|
||||
double sigma_one = atof(arg[4]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
r0[i] = r0_one;
|
||||
epsilon[i] = epsilon_one;
|
||||
sigma[i] = sigma_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double BondFENE::equilibrium_distance(int i)
|
||||
{
|
||||
return 0.97*sigma[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&sigma[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&sigma[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sigma[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENE::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r0sq = r0[type] * r0[type];
|
||||
double rlogarg = 1.0 - rsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
sprintf(str,"FENE bond too long: %d %g",update->ntimestep,sqrt(rsq));
|
||||
error->warning(str);
|
||||
if (rlogarg <= -3.0) error->one("Bad FENE bond");
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fforce = -k[type]/rlogarg;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
double sr2,sr6;
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*epsilon[type]*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (eflag) {
|
||||
eng = -0.5*rfactor * k[type]*r0sq*log(rlogarg);
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
eng += rfactor * (4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]);
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef BOND_FENE_H
|
||||
#define BOND_FENE_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondFENE : public Bond {
|
||||
public:
|
||||
BondFENE();
|
||||
~BondFENE();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double TWO_1_3;
|
||||
double *k,*r0,*epsilon,*sigma;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,292 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
// FENE bond potential, with repulsive LJ, with shift
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_fene_expand.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set all global defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondFENEExpand::BondFENEExpand()
|
||||
{
|
||||
TWO_1_3 = pow(2.0,(1.0/3.0));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondFENEExpand::~BondFENEExpand()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(r0);
|
||||
memory->sfree(epsilon);
|
||||
memory->sfree(sigma);
|
||||
memory->sfree(shift);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,type,factor;
|
||||
double delx,dely,delz,rsq,r0sq,rlogarg,fforce,sr2,sr6,rfactor;
|
||||
double r,rshift,rshiftsq;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5*factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
// force from log term
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
rshift = r - shift[type];
|
||||
rshiftsq = rshift*rshift;
|
||||
r0sq = r0[type] * r0[type];
|
||||
rlogarg = 1.0 - rshiftsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
sprintf(str,"FENE bond too long: %d %d %d %g",
|
||||
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
|
||||
error->warning(str);
|
||||
if (rlogarg <= -3.0) error->one("Bad FENE bond");
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fforce = -k[type]*rshift/rlogarg/r;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rshiftsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*epsilon[type]*sr6*(sr6-0.5)/rshift/r;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (eflag) {
|
||||
energy -= 0.5*rfactor * k[type]*r0sq*log(rlogarg);
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
energy += 0.5*factor *
|
||||
(4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]);
|
||||
}
|
||||
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor * delx*delx*fforce;
|
||||
virial[1] += rfactor * dely*dely*fforce;
|
||||
virial[2] += rfactor * delz*delz*fforce;
|
||||
virial[3] += rfactor * delx*dely*fforce;
|
||||
virial[4] += rfactor * delx*delz*fforce;
|
||||
virial[5] += rfactor * dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"bond:k");
|
||||
r0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:r0");
|
||||
epsilon = (double *) memory->smalloc((n+1)*sizeof(double),"bond:epsilon");
|
||||
sigma = (double *) memory->smalloc((n+1)*sizeof(double),"bond:sigma");
|
||||
shift = (double *) memory->smalloc((n+1)*sizeof(double),"bond:shift");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 6) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double r0_one = atof(arg[2]);
|
||||
double epsilon_one = atof(arg[3]);
|
||||
double sigma_one = atof(arg[4]);
|
||||
double shift_one = atof(arg[5]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
r0[i] = r0_one;
|
||||
epsilon[i] = epsilon_one;
|
||||
sigma[i] = sigma_one;
|
||||
shift[i] = shift_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double BondFENEExpand::equilibrium_distance(int i)
|
||||
{
|
||||
return 0.97*sigma[i] + shift[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&sigma[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&shift[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&sigma[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&shift[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sigma[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&shift[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpand::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r = sqrt(rsq);
|
||||
double rshift = r - shift[type];
|
||||
double rshiftsq = rshift*rshift;
|
||||
double r0sq = r0[type] * r0[type];
|
||||
double rlogarg = 1.0 - rshiftsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
sprintf(str,"FENE bond too long: %d %g",update->ntimestep,sqrt(rsq));
|
||||
error->warning(str);
|
||||
if (rlogarg <= -3.0) error->one("Bad FENE bond");
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fforce = -k[type]*rshift/rlogarg/r;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
double sr2,sr6;
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rshiftsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*epsilon[type]*sr6*(sr6-0.5)/rshift/r;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (eflag) {
|
||||
eng = -0.5*rfactor * k[type]*r0sq*log(rlogarg);
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
eng += rfactor * (4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]);
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef BOND_FENE_EXPAND_H
|
||||
#define BOND_FENE_EXPAND_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondFENEExpand : public Bond {
|
||||
public:
|
||||
BondFENEExpand();
|
||||
~BondFENEExpand();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double TWO_1_3;
|
||||
double *k,*r0,*epsilon,*sigma,*shift;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,204 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_harmonic.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondHarmonic::~BondHarmonic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(r0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,type,factor;
|
||||
double delx,dely,delz,rsq,r,dr,rk,fforce,rfactor;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5 * factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
rk = k[type] * dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fforce = -2.0*rk/r;
|
||||
else fforce = 0.0;
|
||||
|
||||
if (eflag) energy += rfactor * rk*dr;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor*delx*delx*fforce;
|
||||
virial[1] += rfactor*dely*dely*fforce;
|
||||
virial[2] += rfactor*delz*delz*fforce;
|
||||
virial[3] += rfactor*delx*dely*fforce;
|
||||
virial[4] += rfactor*delx*delz*fforce;
|
||||
virial[5] += rfactor*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"bond:k");
|
||||
r0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:r0");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more types
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 3) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double r0_one = atof(arg[2]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
r0[i] = r0_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return an equilbrium bond length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double BondHarmonic::equilibrium_distance(int i)
|
||||
{
|
||||
return r0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonic::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r = sqrt(rsq);
|
||||
double dr = r - r0[type];
|
||||
double rk = k[type] * dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fforce = -2.0*rk/r;
|
||||
else fforce = 0.0;
|
||||
if (eflag) eng = rfactor * rk*dr;
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef BOND_HARMONIC_H
|
||||
#define BOND_HARMONIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondHarmonic : public Bond {
|
||||
public:
|
||||
BondHarmonic() {}
|
||||
~BondHarmonic();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double *k,*r0;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,273 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "bond_hybrid.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define EXTRA 1000
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set all global defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondHybrid::BondHybrid()
|
||||
{
|
||||
nstyles = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondHybrid::~BondHybrid()
|
||||
{
|
||||
if (nstyles) {
|
||||
for (int i = 0; i < nstyles; i++) delete styles[i];
|
||||
delete [] styles;
|
||||
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
|
||||
delete [] keywords;
|
||||
}
|
||||
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(map);
|
||||
delete [] nbondlist;
|
||||
delete [] maxbond;
|
||||
for (int i = 0; i < nstyles; i++)
|
||||
memory->destroy_2d_int_array(bondlist[i]);
|
||||
delete [] bondlist;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n;
|
||||
|
||||
// save ptrs to original bondlist
|
||||
|
||||
int nbondlist_orig = neighbor->nbondlist;
|
||||
int **bondlist_orig = neighbor->bondlist;
|
||||
|
||||
// if this is re-neighbor step, create sub-style bondlists
|
||||
// nbondlist[] = length of each sub-style list
|
||||
// realloc sub-style bondlist if necessary
|
||||
// load sub-style bondlist with 3 values from original bondlist
|
||||
|
||||
if (neighbor->ago == 0) {
|
||||
for (m = 0; m < nstyles; m++) nbondlist[m] = 0;
|
||||
for (i = 0; i < nbondlist_orig; i++)
|
||||
nbondlist[map[bondlist_orig[i][2]]]++;
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (nbondlist[m] > maxbond[m]) {
|
||||
memory->destroy_2d_int_array(bondlist[m]);
|
||||
maxbond[m] = nbondlist[m] + EXTRA;
|
||||
bondlist[m] = (int **)
|
||||
memory->create_2d_int_array(maxbond[m],3,"bond_hybrid:bondlist");
|
||||
}
|
||||
nbondlist[m] = 0;
|
||||
}
|
||||
for (i = 0; i < nbondlist_orig; i++) {
|
||||
m = map[bondlist_orig[i][2]];
|
||||
n = nbondlist[m];
|
||||
bondlist[m][n][0] = bondlist_orig[i][0];
|
||||
bondlist[m][n][1] = bondlist_orig[i][1];
|
||||
bondlist[m][n][2] = bondlist_orig[i][2];
|
||||
nbondlist[m]++;
|
||||
}
|
||||
}
|
||||
|
||||
// call each sub-style's compute function
|
||||
// must set neighbor->bondlist to sub-style bondlist before call
|
||||
// accumulate sub-style energy,virial in hybrid's energy,virial
|
||||
|
||||
energy = 0.0;
|
||||
eng_vdwl = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (styles[m] == NULL) continue;
|
||||
neighbor->nbondlist = nbondlist[m];
|
||||
neighbor->bondlist = bondlist[m];
|
||||
styles[m]->compute(eflag,vflag);
|
||||
if (eflag) {
|
||||
energy += styles[m]->energy;
|
||||
eng_vdwl += styles[m]->eng_vdwl;
|
||||
}
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
|
||||
}
|
||||
|
||||
// restore ptrs to original bondlist
|
||||
|
||||
neighbor->nbondlist = nbondlist_orig;
|
||||
neighbor->bondlist = bondlist_orig;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
map = (int *) memory->smalloc((n+1)*sizeof(int),"bond:map");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
|
||||
nbondlist = new int[nstyles];
|
||||
maxbond = new int[nstyles];
|
||||
bondlist = new int**[nstyles];
|
||||
for (int m = 0; m < nstyles; m++) maxbond[m] = 0;
|
||||
for (int m = 0; m < nstyles; m++) bondlist[m] = NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create one bond style for each arg in list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::settings(int narg, char **arg)
|
||||
{
|
||||
nstyles = narg;
|
||||
styles = new Bond*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
for (int i = 0; i < m; i++)
|
||||
if (strcmp(arg[m],arg[i]) == 0)
|
||||
error->all("Bond style hybrid cannot use same bond style twice");
|
||||
if (strcmp(arg[m],"hybrid") == 0)
|
||||
error->all("Bond style hybrid cannot have hybrid as an argument");
|
||||
styles[m] = force->new_bond(arg[m]);
|
||||
keywords[m] = new char[strlen(arg[m])+1];
|
||||
strcpy(keywords[m],arg[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::coeff(int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
// 2nd arg = bond style name (harmonic, fene, etc)
|
||||
|
||||
int m;
|
||||
for (m = 0; m < nstyles; m++)
|
||||
if (strcmp(arg[1],keywords[m]) == 0) break;
|
||||
if (m == nstyles) error->all("Bond coeff for hybrid has invalid style");
|
||||
|
||||
// set low-level coefficients for each bondtype
|
||||
// replace 2nd arg with i, call coeff() with no 1st arg
|
||||
// if sub-style is NULL for "none", still set setflag
|
||||
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
sprintf(arg[1],"%d",i);
|
||||
map[i] = m;
|
||||
if (styles[m]) styles[m]->coeff(narg-1,&arg[1]);
|
||||
setflag[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::init_style()
|
||||
{
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) styles[m]->init_style();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return an equilbrium bond length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double BondHybrid::equilibrium_distance(int i)
|
||||
{
|
||||
return styles[map[i]]->equilibrium_distance(i);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&nstyles,sizeof(int),1,fp);
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
n = strlen(keywords[m]) + 1;
|
||||
fwrite(&n,sizeof(int),1,fp);
|
||||
fwrite(keywords[m],sizeof(char),n,fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
int me = comm->me;
|
||||
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
|
||||
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
|
||||
styles = new Bond*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
if (me == 0) fread(&n,sizeof(int),1,fp);
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
keywords[m] = new char[n];
|
||||
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
|
||||
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
|
||||
styles[m] = force->new_bond(keywords[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHybrid::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
if (styles[map[type]])
|
||||
styles[map[type]]->single(type,rsq,i,j,rfactor,eflag,fforce,eng);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int BondHybrid::memory_usage()
|
||||
{
|
||||
int bytes = 0;
|
||||
for (int m = 0; m < nstyles; m++) bytes += maxbond[m]*3 * sizeof(int);
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) bytes += styles[m]->memory_usage();
|
||||
return bytes;
|
||||
}
|
||||
@ -1,214 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Jeff Greathouse (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_morse.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondMorse::~BondMorse()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(d0);
|
||||
memory->sfree(alpha);
|
||||
memory->sfree(r0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,type,factor;
|
||||
double delx,dely,delz,rsq,r,dr,fforce,rfactor,ralpha;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5 * factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
ralpha = exp(-alpha[type]*dr);
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fforce = -2.0*d0[type]*alpha[type]*(1-ralpha)*ralpha/r;
|
||||
else fforce = 0.0;
|
||||
|
||||
if (eflag) energy += rfactor * d0[type]*(1-ralpha)*(1-ralpha);
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor*delx*delx*fforce;
|
||||
virial[1] += rfactor*dely*dely*fforce;
|
||||
virial[2] += rfactor*delz*delz*fforce;
|
||||
virial[3] += rfactor*delx*dely*fforce;
|
||||
virial[4] += rfactor*delx*delz*fforce;
|
||||
virial[5] += rfactor*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
d0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:d0");
|
||||
alpha = (double *) memory->smalloc((n+1)*sizeof(double),"bond:alpha");
|
||||
r0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:r0");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 4) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double d0_one = atof(arg[1]);
|
||||
double alpha_one = atof(arg[2]);
|
||||
double r0_one = atof(arg[3]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
d0[i] = d0_one;
|
||||
alpha[i] = alpha_one;
|
||||
r0[i] = r0_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return an equilbrium bond length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double BondMorse::equilibrium_distance(int i)
|
||||
{
|
||||
return r0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&d0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&alpha[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&d0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&alpha[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&d0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&alpha[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondMorse::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r = sqrt(rsq);
|
||||
double dr = r - r0[type];
|
||||
double ralpha = exp(-alpha[type]*dr);
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fforce = -2.0*d0[type]*alpha[type]*(1-ralpha)*ralpha/r;
|
||||
else fforce = 0.0;
|
||||
if (eflag) eng = rfactor * d0[type]*(1-ralpha)*(1-ralpha);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef BOND_MORSE_H
|
||||
#define BOND_MORSE_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondMorse : public Bond {
|
||||
public:
|
||||
BondMorse() {}
|
||||
~BondMorse();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double *d0,*alpha,*r0;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,211 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_nonlinear.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondNonlinear::~BondNonlinear()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(epsilon);
|
||||
memory->sfree(r0);
|
||||
memory->sfree(lamda);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,type,factor;
|
||||
double delx,dely,delz,rsq,r,dr,drsq,lamdasq,denom,denomsq,fforce,rfactor;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5 * factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
drsq = dr*dr;
|
||||
lamdasq = lamda[type]*lamda[type];
|
||||
denom = lamdasq - drsq;
|
||||
denomsq = denom*denom;
|
||||
|
||||
// force & energy
|
||||
|
||||
fforce = -epsilon[type]/r * 2.0*dr*lamdasq/denomsq;
|
||||
if (eflag) energy += rfactor * epsilon[type] * drsq / denom;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor*delx*delx*fforce;
|
||||
virial[1] += rfactor*dely*dely*fforce;
|
||||
virial[2] += rfactor*delz*delz*fforce;
|
||||
virial[3] += rfactor*delx*dely*fforce;
|
||||
virial[4] += rfactor*delx*delz*fforce;
|
||||
virial[5] += rfactor*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
epsilon = (double *) memory->smalloc((n+1)*sizeof(double),"bond:epsilon");
|
||||
r0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:r0");
|
||||
lamda = (double *) memory->smalloc((n+1)*sizeof(double),"bond:lamda");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 4) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double epsilon_one = atof(arg[1]);
|
||||
double r0_one = atof(arg[2]);
|
||||
double lamda_one = atof(arg[3]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
epsilon[i] = epsilon_one;
|
||||
r0[i] = r0_one;
|
||||
lamda[i] = lamda_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double BondNonlinear::equilibrium_distance(int i)
|
||||
{
|
||||
return r0[i];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&lamda[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&lamda[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&lamda[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinear::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r = sqrt(rsq);
|
||||
double dr = r - r0[type];
|
||||
double drsq = dr*dr;
|
||||
double lamdasq = lamda[type]*lamda[type];
|
||||
double denom = lamdasq - drsq;
|
||||
double denomsq = denom*denom;
|
||||
|
||||
// force & energy
|
||||
|
||||
fforce = -epsilon[type]/r * 2.0*dr*lamdasq/denomsq;
|
||||
if (eflag) eng = rfactor * epsilon[type] * drsq / denom;
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef BOND_NONLINEAR_H
|
||||
#define BOND_NONLINEAR_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondNonlinear : public Bond {
|
||||
public:
|
||||
BondNonlinear() {}
|
||||
~BondNonlinear();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double *epsilon,*r0,*lamda;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,340 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Chris Lorenz and Mark Stevens (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "bond_quartic.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondQuartic::BondQuartic()
|
||||
{
|
||||
TWO_1_3 = pow(2.0,(1.0/3.0));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
BondQuartic::~BondQuartic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(b1);
|
||||
memory->sfree(b2);
|
||||
memory->sfree(rc);
|
||||
memory->sfree(u0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::compute(int eflag, int vflag)
|
||||
{
|
||||
int i1,i2,n,m,type,factor,itype,jtype;
|
||||
double delx,dely,delz,r,rsq,dr,r2,ra,rb,fforce,sr2,sr6,rfactor;
|
||||
Pair::One one;
|
||||
|
||||
energy = 0.0;
|
||||
eng_vdwl = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **cutsq = force->pair->cutsq;
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **bondlist = neighbor->bondlist;
|
||||
int nbondlist = neighbor->nbondlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nbondlist; n++) {
|
||||
|
||||
// skip bond if already broken
|
||||
|
||||
if (bondlist[n][2] <= 0) continue;
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
if (newton_bond) factor = 2;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.5*factor;
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
// if bond breaks, set type to 0
|
||||
// both in temporary bondlist and permanent bond_type
|
||||
// if this proc owns both atoms,
|
||||
// negate bond_type twice if other atom stores it
|
||||
// if other proc owns 2nd atom, other proc will also break bond
|
||||
|
||||
if (rsq > rc[type]*rc[type]) {
|
||||
bondlist[n][2] = 0;
|
||||
for (m = 0; m < atom->num_bond[i1]; m++)
|
||||
if (atom->bond_atom[i1][m] == atom->tag[i2])
|
||||
atom->bond_type[i1][m] = 0;
|
||||
if (i2 < atom->nlocal)
|
||||
for (m = 0; m < atom->num_bond[i2]; m++)
|
||||
if (atom->bond_atom[i2][m] == atom->tag[i1])
|
||||
atom->bond_type[i2][m] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// subtract out pairwise contribution from 2 atoms via pair->single()
|
||||
// required since special_bond = 1,1,1
|
||||
|
||||
itype = atom->type[i1];
|
||||
jtype = atom->type[i2];
|
||||
|
||||
if (rsq < cutsq[itype][jtype]) {
|
||||
force->pair->single(i1,i2,itype,jtype,rsq,1.0,1.0,eflag,one);
|
||||
fforce = -one.fforce;
|
||||
if (eflag) eng_vdwl -= one.eng_vdwl + one.eng_coul;
|
||||
} else fforce = 0.0;
|
||||
|
||||
// quartic bond
|
||||
// 1st portion is from quartic term
|
||||
// 2nd portion is from LJ term cut at 2^(1/6) with eps = sigma = 1.0
|
||||
|
||||
r = sqrt(rsq);
|
||||
dr = r - rc[type];
|
||||
r2 = dr*dr;
|
||||
ra = dr - b1[type];
|
||||
rb = dr - b2[type];
|
||||
fforce += -k[type]/r * (r2*(ra+rb) + 2.0*dr*ra*rb);
|
||||
|
||||
if (rsq < TWO_1_3) {
|
||||
sr2 = 1.0/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
energy += rfactor*(k[type]*r2*ra*rb + u0[type]);
|
||||
if (rsq < TWO_1_3) energy += rfactor * (4.0*sr6*(sr6-1.0) + 1.0);
|
||||
}
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fforce;
|
||||
f[i2][1] -= dely*fforce;
|
||||
f[i2][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor * delx*delx*fforce;
|
||||
virial[1] += rfactor * dely*dely*fforce;
|
||||
virial[2] += rfactor * delz*delz*fforce;
|
||||
virial[3] += rfactor * delx*dely*fforce;
|
||||
virial[4] += rfactor * delx*delz*fforce;
|
||||
virial[5] += rfactor * dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nbondtypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"bond:k");
|
||||
b1 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:b1");
|
||||
b2 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:b2");
|
||||
rc = (double *) memory->smalloc((n+1)*sizeof(double),"bond:rc");
|
||||
u0 = (double *) memory->smalloc((n+1)*sizeof(double),"bond:u0");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"bond:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more types
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 6) error->all("Incorrect args for bond coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double b1_one = atof(arg[2]);
|
||||
double b2_one = atof(arg[3]);
|
||||
double rc_one = atof(arg[4]);
|
||||
double u0_one = atof(arg[5]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
b1[i] = b1_one;
|
||||
b2[i] = b2_one;
|
||||
rc[i] = rc_one;
|
||||
u0[i] = u0_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for bond coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if pair defined and special_bond settings are valid
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::init_style()
|
||||
{
|
||||
if (force->pair == NULL || force->pair->single_enable == 0)
|
||||
error->all("Pair style does not support bond_style quartic");
|
||||
if (force->angle)
|
||||
error->all("Bond style quartic cannot be used with 3,4-body interactions");
|
||||
if (force->dihedral)
|
||||
error->all("Bond style quartic cannot be used with 3,4-body interactions");
|
||||
if (force->improper)
|
||||
error->all("Bond style quartic cannot be used with 3,4-body interactions");
|
||||
|
||||
// special bonds must be 1 1 1
|
||||
|
||||
if (force->special_lj[1] != 1.0 || force->special_lj[2] != 1.0 ||
|
||||
force->special_lj[3] != 1.0)
|
||||
error->all("Must use special bonds = 1,1,1 with bond style quartic");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return an equilbrium bond length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double BondQuartic::equilibrium_distance(int i)
|
||||
{
|
||||
return 0.97;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&b1[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&b2[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&rc[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fwrite(&u0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&b1[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&b2[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&rc[1],sizeof(double),atom->nbondtypes,fp);
|
||||
fread(&u0[1],sizeof(double),atom->nbondtypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&b1[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&b2[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&rc[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&u0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondQuartic::single(int type, double rsq, int i, int j, double rfactor,
|
||||
int eflag, double &fforce, double &eng)
|
||||
{
|
||||
double r,dr,r2,ra,rb,sr2,sr6;
|
||||
|
||||
fforce = eng = 0.0;
|
||||
if (type <= 0) return;
|
||||
|
||||
// subtract out pairwise contribution from 2 atoms via pair->single()
|
||||
// required since special_bond = 1,1,1
|
||||
|
||||
int itype = atom->type[i];
|
||||
int jtype = atom->type[j];
|
||||
|
||||
if (rsq < force->pair->cutsq[itype][jtype]) {
|
||||
Pair::One one;
|
||||
force->pair->single(i,j,itype,jtype,rsq,1.0,1.0,eflag,one);
|
||||
fforce = -one.fforce;
|
||||
if (eflag) eng = -one.eng_coul - one.eng_vdwl;
|
||||
}
|
||||
|
||||
// quartic bond
|
||||
// 1st portion is from quartic term
|
||||
// 2nd portion is from LJ term cut at 2^(1/6) with eps = sigma = 1.0
|
||||
|
||||
r = sqrt(rsq);
|
||||
dr = r - rc[type];
|
||||
r2 = dr*dr;
|
||||
ra = dr - b1[type];
|
||||
rb = dr - b2[type];
|
||||
fforce += -k[type]/r * (r2*(ra+rb) + 2.0*dr*ra*rb);
|
||||
|
||||
if (rsq < TWO_1_3) {
|
||||
sr2 = 1.0/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fforce += 48.0*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
eng += rfactor*(k[type]*r2*ra*rb + u0[type]);
|
||||
if (rsq < TWO_1_3) eng += rfactor * (4.0*sr6*(sr6-1.0) + 1.0);
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#ifndef BOND_QUARTIC_H
|
||||
#define BOND_QUARTIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bond.h"
|
||||
|
||||
class BondQuartic : public Bond {
|
||||
public:
|
||||
BondQuartic();
|
||||
~BondQuartic();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
void init_style();
|
||||
double equilibrium_distance(int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void single(int, double, int, int, double, int, double &, double &);
|
||||
|
||||
private:
|
||||
double TWO_1_3;
|
||||
double *k,*b1,*b2,*rc,*u0;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -257,7 +257,6 @@ void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
list[i] = 1;
|
||||
if (j >= nall) {
|
||||
if (special_coul[j/nall] == 0.0 && special_lj[j/nall] == 0.0) continue;
|
||||
j %= nall;
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "dihedral.h"
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set dihedral contribution to Vdwl and Coulombic energy to 0.0
|
||||
DihedralCharmm will override this
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
Dihedral::Dihedral()
|
||||
{
|
||||
allocated = 0;
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
PI = 4.0*atan(1.0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if all coeffs are set
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Dihedral::init()
|
||||
{
|
||||
if (!allocated) error->all("Dihedral coeffs are not set");
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++)
|
||||
if (setflag[i] == 0) error->all("All dihedral coeffs are not set");
|
||||
init_style();
|
||||
}
|
||||
|
||||
@ -1,450 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "dihedral_charmm.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "pair_lj_charmm_coul_charmm.h"
|
||||
#include "pair_lj_charmm_coul_charmm_implicit.h"
|
||||
#include "pair_lj_charmm_coul_long.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralCharmm::~DihedralCharmm()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(multiplicity);
|
||||
memory->sfree(shift);
|
||||
memory->sfree(cos_shift);
|
||||
memory->sfree(sin_shift);
|
||||
memory->sfree(weight);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z;
|
||||
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
|
||||
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
|
||||
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
|
||||
double c,s,p,sx1,sx2,sx12,sy1,sy2,sy12,sz1,sz2,sz12;
|
||||
int itype,jtype;
|
||||
double delx,dely,delz,rsq,r2inv,r6inv;
|
||||
double fforce,forcecoul,forcelj,phicoul,philj;
|
||||
|
||||
energy = 0.0;
|
||||
eng_coul = eng_vdwl = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
double *q = atom->q;
|
||||
int *atomtype = atom->type;
|
||||
int **dihedrallist = neighbor->dihedrallist;
|
||||
int ndihedrallist = neighbor->ndihedrallist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
double qqrd2e = force->qqrd2e;
|
||||
|
||||
for (n = 0; n < ndihedrallist; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
ax = vb1y*vb2zm - vb1z*vb2ym;
|
||||
ay = vb1z*vb2xm - vb1x*vb2zm;
|
||||
az = vb1x*vb2ym - vb1y*vb2xm;
|
||||
bx = vb3y*vb2zm - vb3z*vb2ym;
|
||||
by = vb3z*vb2xm - vb3x*vb2zm;
|
||||
bz = vb3x*vb2ym - vb3y*vb2xm;
|
||||
|
||||
rasq = ax*ax + ay*ay + az*az;
|
||||
rbsq = bx*bx + by*by + bz*bz;
|
||||
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
|
||||
rg = sqrt(rgsq);
|
||||
|
||||
rginv = ra2inv = rb2inv = 0.0;
|
||||
if (rg > 0) rginv = 1.0/rg;
|
||||
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||
rabinv = sqrt(ra2inv*rb2inv);
|
||||
|
||||
c = (ax*bx + ay*by + az*bz)*rabinv;
|
||||
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me;
|
||||
MPI_Comm_rank(world,&me);
|
||||
if (screen) {
|
||||
fprintf(screen,"Dihedral problem: %d %d %d %d %d %d\n",
|
||||
me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
m = multiplicity[type];
|
||||
p = 1.0;
|
||||
df1 = 0.0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
ddf1 = p*c - df1*s;
|
||||
df1 = p*s + df1*c;
|
||||
p = ddf1;
|
||||
}
|
||||
|
||||
p = p*cos_shift[type] + df1*sin_shift[type];
|
||||
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
|
||||
df1 *= -m;
|
||||
p += 1.0;
|
||||
|
||||
if (m == 0) {
|
||||
p = 1.0 + cos_shift[type];
|
||||
df1 = 0.0;
|
||||
}
|
||||
|
||||
if (eflag) energy += rfactor * k[type] * p;
|
||||
|
||||
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
|
||||
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
|
||||
fga = fg*ra2inv*rginv;
|
||||
hgb = hg*rb2inv*rginv;
|
||||
gaa = -ra2inv*rg;
|
||||
gbb = rb2inv*rg;
|
||||
|
||||
dtfx = gaa*ax;
|
||||
dtfy = gaa*ay;
|
||||
dtfz = gaa*az;
|
||||
dtgx = fga*ax - hgb*bx;
|
||||
dtgy = fga*ay - hgb*by;
|
||||
dtgz = fga*az - hgb*bz;
|
||||
dthx = gbb*bx;
|
||||
dthy = gbb*by;
|
||||
dthz = gbb*bz;
|
||||
|
||||
df = k[type] * df1;
|
||||
|
||||
sx1 = df*dtfx;
|
||||
sy1 = df*dtfy;
|
||||
sz1 = df*dtfz;
|
||||
sx2 = -df*dtgx;
|
||||
sy2 = -df*dtgy;
|
||||
sz2 = -df*dtgz;
|
||||
sx12 = df*dthx;
|
||||
sy12 = df*dthy;
|
||||
sz12 = df*dthz;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
|
||||
// 1-4 LJ and Coulomb interactions
|
||||
// force, energy, and virial
|
||||
|
||||
if (weight[type] > 0.0) {
|
||||
|
||||
itype = atomtype[i1];
|
||||
jtype = atomtype[i4];
|
||||
|
||||
delx = x[i1][0] - x[i4][0];
|
||||
dely = x[i1][1] - x[i4][1];
|
||||
delz = x[i1][2] - x[i4][2];
|
||||
domain->minimum_image(&delx,&dely,&delz);
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r2inv = 1.0/rsq;
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
|
||||
if (implicitflag) forcecoul = qqrd2e * q[i1]*q[i4]*r2inv;
|
||||
else forcecoul = qqrd2e * q[i1]*q[i4]*sqrt(r2inv);
|
||||
forcelj = r6inv * (lj14_1[itype][jtype]*r6inv - lj14_2[itype][jtype]);
|
||||
fforce = weight[type] * (forcelj+forcecoul)*r2inv;
|
||||
|
||||
if (eflag) {
|
||||
phicoul = weight[type] * rfactor * forcecoul;
|
||||
philj = r6inv * (lj14_3[itype][jtype]*r6inv - lj14_4[itype][jtype]);
|
||||
philj = weight[type] * rfactor * philj;
|
||||
eng_coul += phicoul;
|
||||
eng_vdwl += philj;
|
||||
}
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] += delx*fforce;
|
||||
f[i1][1] += dely*fforce;
|
||||
f[i1][2] += delz*fforce;
|
||||
}
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= delx*fforce;
|
||||
f[i4][1] -= dely*fforce;
|
||||
f[i4][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor * delx*delx*fforce;
|
||||
virial[1] += rfactor * dely*dely*fforce;
|
||||
virial[2] += rfactor * delz*delz*fforce;
|
||||
virial[3] += rfactor * delx*dely*fforce;
|
||||
virial[4] += rfactor * delx*delz*fforce;
|
||||
virial[5] += rfactor * dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k");
|
||||
multiplicity = (int *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:multiplicity");
|
||||
shift = (int *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:shift");
|
||||
cos_shift = (double *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:cos_shift");
|
||||
sin_shift = (double *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:sin_shift");
|
||||
weight = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:weight");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this dihedral style");
|
||||
if (narg != 5) error->all("Incorrect args for dihedral coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
// require integer values of shift for backwards compatibility
|
||||
// arbitrary phase angle shift could be allowed, but would break
|
||||
// backwards compatibility and is probably not needed
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
int multiplicity_one = atoi(arg[2]);
|
||||
int shift_one = atoi(arg[3]);
|
||||
double weight_one = atof(arg[4]);
|
||||
|
||||
if (multiplicity_one < 0)
|
||||
error->all("Incorrect multiplicity arg for dihedral coefficients");
|
||||
if (weight_one < 0.0 || weight_one > 1.0)
|
||||
error->all("Incorrect weight arg for dihedral coefficients");
|
||||
|
||||
double PI = 4.0*atan(1.0);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
shift[i] = shift_one;
|
||||
cos_shift[i] = cos(PI*shift_one/180.0);
|
||||
sin_shift[i] = sin(PI*shift_one/180.0);
|
||||
multiplicity[i] = multiplicity_one;
|
||||
weight[i] = weight_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for dihedral coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
error check and initialize all values needed for force computation
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::init_style()
|
||||
{
|
||||
// set local ptrs to LJ 14 arrays setup by pair
|
||||
|
||||
Pair *anypair;
|
||||
if (anypair = force->pair_match("lj/charmm/coul/charmm")) {
|
||||
PairLJCharmmCoulCharmm *pair = (PairLJCharmmCoulCharmm *) anypair;
|
||||
lj14_1 = pair->lj14_1;
|
||||
lj14_2 = pair->lj14_2;
|
||||
lj14_3 = pair->lj14_3;
|
||||
lj14_4 = pair->lj14_4;
|
||||
implicitflag = 0;
|
||||
} else if (anypair = force->pair_match("lj/charmm/coul/charmm/implicit")) {
|
||||
PairLJCharmmCoulCharmmImplicit *pair =
|
||||
(PairLJCharmmCoulCharmmImplicit *) anypair;
|
||||
lj14_1 = pair->lj14_1;
|
||||
lj14_2 = pair->lj14_2;
|
||||
lj14_3 = pair->lj14_3;
|
||||
lj14_4 = pair->lj14_4;
|
||||
implicitflag = 1;
|
||||
} else if (anypair = force->pair_match("lj/charmm/coul/long")) {
|
||||
PairLJCharmmCoulLong *pair = (PairLJCharmmCoulLong *) anypair;
|
||||
lj14_1 = pair->lj14_1;
|
||||
lj14_2 = pair->lj14_2;
|
||||
lj14_3 = pair->lj14_3;
|
||||
lj14_4 = pair->lj14_4;
|
||||
implicitflag = 0;
|
||||
} else error->all("Pair style is incompatible with DihedralCharmm");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fwrite(&shift[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fwrite(&weight[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmm::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fread(&shift[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fread(&weight[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&multiplicity[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||
MPI_Bcast(&shift[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||
MPI_Bcast(&weight[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
|
||||
double PI = 4.0*atan(1.0);
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++) {
|
||||
setflag[i] = 1;
|
||||
cos_shift[i] = cos(PI*shift[i]/180.0);
|
||||
sin_shift[i] = sin(PI*shift[i]/180.0);
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_CHARMM_H
|
||||
#define DIHEDRAL_CHARMM_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralCharmm : public Dihedral {
|
||||
public:
|
||||
DihedralCharmm() {}
|
||||
~DihedralCharmm();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void init_style();
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *k,*weight,*cos_shift,*sin_shift;
|
||||
int *multiplicity,*shift;
|
||||
double **lj14_1,**lj14_2,**lj14_3,**lj14_4;
|
||||
int implicitflag;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,356 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "dihedral_harmonic.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralHarmonic::~DihedralHarmonic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(sign);
|
||||
memory->sfree(multiplicity);
|
||||
memory->sfree(cos_shift);
|
||||
memory->sfree(sin_shift);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonic::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z;
|
||||
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
|
||||
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
|
||||
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
|
||||
double c,s,p,sx1,sx2,sx12,sy1,sy2,sy12,sz1,sz2,sz12;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **dihedrallist = neighbor->dihedrallist;
|
||||
int ndihedrallist = neighbor->ndihedrallist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < ndihedrallist; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
// c,s calculation
|
||||
|
||||
ax = vb1y*vb2zm - vb1z*vb2ym;
|
||||
ay = vb1z*vb2xm - vb1x*vb2zm;
|
||||
az = vb1x*vb2ym - vb1y*vb2xm;
|
||||
bx = vb3y*vb2zm - vb3z*vb2ym;
|
||||
by = vb3z*vb2xm - vb3x*vb2zm;
|
||||
bz = vb3x*vb2ym - vb3y*vb2xm;
|
||||
|
||||
rasq = ax*ax + ay*ay + az*az;
|
||||
rbsq = bx*bx + by*by + bz*bz;
|
||||
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
|
||||
rg = sqrt(rgsq);
|
||||
|
||||
rginv = ra2inv = rb2inv = 0.0;
|
||||
if (rg > 0) rginv = 1.0/rg;
|
||||
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||
rabinv = sqrt(ra2inv*rb2inv);
|
||||
|
||||
c = (ax*bx + ay*by + az*bz)*rabinv;
|
||||
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me;
|
||||
MPI_Comm_rank(world,&me);
|
||||
if (screen) {
|
||||
fprintf(screen,"Dihedral problem: %d %d %d %d %d %d\n",
|
||||
me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
m = multiplicity[type];
|
||||
p = 1.0;
|
||||
df1 = 0.0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
ddf1 = p*c - df1*s;
|
||||
df1 = p*s + df1*c;
|
||||
p = ddf1;
|
||||
}
|
||||
|
||||
p = p*cos_shift[type] + df1*sin_shift[type];
|
||||
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
|
||||
df1 *= -m;
|
||||
p += 1.0;
|
||||
|
||||
if (m == 0) {
|
||||
p = 1.0 + cos_shift[type];
|
||||
df1 = 0.0;
|
||||
}
|
||||
|
||||
if (eflag) energy += rfactor * k[type] * p;
|
||||
|
||||
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
|
||||
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
|
||||
fga = fg*ra2inv*rginv;
|
||||
hgb = hg*rb2inv*rginv;
|
||||
gaa = -ra2inv*rg;
|
||||
gbb = rb2inv*rg;
|
||||
|
||||
dtfx = gaa*ax;
|
||||
dtfy = gaa*ay;
|
||||
dtfz = gaa*az;
|
||||
dtgx = fga*ax - hgb*bx;
|
||||
dtgy = fga*ay - hgb*by;
|
||||
dtgz = fga*az - hgb*bz;
|
||||
dthx = gbb*bx;
|
||||
dthy = gbb*by;
|
||||
dthz = gbb*bz;
|
||||
|
||||
df = k[type] * df1;
|
||||
|
||||
sx1 = df*dtfx;
|
||||
sy1 = df*dtfy;
|
||||
sz1 = df*dtfz;
|
||||
sx2 = -df*dtgx;
|
||||
sy2 = -df*dtgy;
|
||||
sz2 = -df*dtgz;
|
||||
sx12 = df*dthx;
|
||||
sy12 = df*dthy;
|
||||
sz12 = df*dthz;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k");
|
||||
sign = (int *) memory->smalloc((n+1)*sizeof(double),"dihedral:sign");
|
||||
multiplicity = (int *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:multiplicity");
|
||||
cos_shift = (double *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:cos_shift");
|
||||
sin_shift = (double *)
|
||||
memory->smalloc((n+1)*sizeof(double),"dihedral:sin_shift");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonic::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this dihedral style");
|
||||
if (narg != 4) error->all("Incorrect args for dihedral coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
int sign_one = atoi(arg[2]);
|
||||
int multiplicity_one = atoi(arg[3]);
|
||||
|
||||
// require sign = +/- 1 for backwards compatibility
|
||||
// arbitrary phase angle shift could be allowed, but would break
|
||||
// backwards compatibility and is probably not needed
|
||||
|
||||
if (sign_one != -1 && sign_one != 1)
|
||||
error->all("Incorrect sign arg for dihedral coefficients");
|
||||
if (multiplicity_one < 0)
|
||||
error->all("Incorrect multiplicity arg for dihedral coefficients");
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
sign[i] = sign_one;
|
||||
if (sign[i] == 1) {
|
||||
cos_shift[i] = 1;
|
||||
sin_shift[i] = 0;
|
||||
} else {
|
||||
cos_shift[i] = -1;
|
||||
sin_shift[i] = 0;
|
||||
}
|
||||
multiplicity[i] = multiplicity_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for dihedral coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&sign[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fwrite(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&sign[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
fread(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sign[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||
MPI_Bcast(&multiplicity[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++) {
|
||||
setflag[i] = 1;
|
||||
if (sign[i] == 1) {
|
||||
cos_shift[i] = 1;
|
||||
sin_shift[i] = 0;
|
||||
} else {
|
||||
cos_shift[i] = -1;
|
||||
sin_shift[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_HARMONIC_H
|
||||
#define DIHEDRAL_HARMONIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralHarmonic : public Dihedral {
|
||||
public:
|
||||
DihedralHarmonic() {}
|
||||
~DihedralHarmonic();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *k,*cos_shift,*sin_shift;
|
||||
int *sign,*multiplicity;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,340 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Naveen Michaud-Agrawal (Johns Hopkins U) and
|
||||
Mark Stevens (Sandia)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "mpi.h"
|
||||
#include "dihedral_helix.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
#define SMALLER 0.00001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralHelix::~DihedralHelix()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(aphi);
|
||||
memory->sfree(bphi);
|
||||
memory->sfree(cphi);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelix::compute(int eflag, int vflag)
|
||||
{
|
||||
int n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z,sb1;
|
||||
double sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx1,sx2,sx12,sy1,sy2,sy12;
|
||||
double sz1,sz2,sz12,s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **dihedrallist = neighbor->dihedrallist;
|
||||
int ndihedrallist = neighbor->ndihedrallist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < ndihedrallist; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
cx = vb1y*vb2z - vb1z*vb2y;
|
||||
cy = vb1z*vb2x - vb1x*vb2z;
|
||||
cz = vb1x*vb2y - vb1y*vb2x;
|
||||
cmag = sqrt(cx*cx + cy*cy + cz*cz);
|
||||
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me;
|
||||
MPI_Comm_rank(world,&me);
|
||||
if (screen) {
|
||||
fprintf(screen,"Dihedral problem: %d %d %d %d %d %d\n",
|
||||
me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
phi = acos(c);
|
||||
if (dx < 0.0) phi *= -1.0;
|
||||
si = sin(phi);
|
||||
if (fabs(si) < SMALLER) si = SMALLER;
|
||||
siinv = 1.0/si;
|
||||
|
||||
p = aphi[type]*(1.0 - c) + bphi[type]*(1.0 + cos(3.0*phi)) +
|
||||
cphi[type]*(1.0 + cos(phi + 0.25*PI));
|
||||
pd = -aphi[type] + 3.0*bphi[type]*sin(3.0*phi)*siinv +
|
||||
cphi[type]*sin(phi + 0.25*PI)*siinv;
|
||||
|
||||
if (eflag) energy += rfactor * p;
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = -c*sb1*s1;
|
||||
a22 = sb2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = -c*sb3*s2;
|
||||
a12 = r12c1 * (c1mag*c*s1 + c2mag*s12);
|
||||
a13 = rb1*rb3*s12;
|
||||
a23 = r12c2 * (-c2mag*c*s2 - c1mag*s12);
|
||||
|
||||
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelix::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
aphi = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:aphi");
|
||||
bphi = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:bphi");
|
||||
cphi = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:cphi");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs from one line in input script
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelix::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this dihedral style");
|
||||
if (narg != 4) error->all("Incorrect args for dihedral coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
double aphi_one = atof(arg[1]);
|
||||
double bphi_one = atof(arg[2]);
|
||||
double cphi_one = atof(arg[3]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
aphi[i] = aphi_one;
|
||||
bphi[i] = bphi_one;
|
||||
cphi[i] = cphi_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for dihedral coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelix::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&aphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&bphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&cphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelix::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&aphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&bphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&cphi[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
MPI_Bcast(&aphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&bphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_HELIX_H
|
||||
#define DIHEDRAL_HELIX_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralHelix : public Dihedral {
|
||||
public:
|
||||
DihedralHelix() {}
|
||||
~DihedralHelix();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *aphi,*bphi,*cphi;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,259 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "dihedral_hybrid.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define EXTRA 1000
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set all global defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralHybrid::DihedralHybrid()
|
||||
{
|
||||
nstyles = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralHybrid::~DihedralHybrid()
|
||||
{
|
||||
if (nstyles) {
|
||||
for (int i = 0; i < nstyles; i++) delete styles[i];
|
||||
delete [] styles;
|
||||
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
|
||||
delete [] keywords;
|
||||
}
|
||||
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(map);
|
||||
delete [] ndihedrallist;
|
||||
delete [] maxdihedral;
|
||||
for (int i = 0; i < nstyles; i++)
|
||||
memory->destroy_2d_int_array(dihedrallist[i]);
|
||||
delete [] dihedrallist;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n;
|
||||
|
||||
// save ptrs to original dihedrallist
|
||||
|
||||
int ndihedrallist_orig = neighbor->ndihedrallist;
|
||||
int **dihedrallist_orig = neighbor->dihedrallist;
|
||||
|
||||
// if this is re-neighbor step, create sub-style dihedrallists
|
||||
// ndihedrallist[] = length of each sub-style list
|
||||
// realloc sub-style dihedrallist if necessary
|
||||
// load sub-style dihedrallist with 5 values from original dihedrallist
|
||||
|
||||
if (neighbor->ago == 0) {
|
||||
for (m = 0; m < nstyles; m++) ndihedrallist[m] = 0;
|
||||
for (i = 0; i < ndihedrallist_orig; i++)
|
||||
ndihedrallist[map[dihedrallist_orig[i][4]]]++;
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (ndihedrallist[m] > maxdihedral[m]) {
|
||||
memory->destroy_2d_int_array(dihedrallist[m]);
|
||||
maxdihedral[m] = ndihedrallist[m] + EXTRA;
|
||||
dihedrallist[m] = (int **)
|
||||
memory->create_2d_int_array(maxdihedral[m],5,
|
||||
"dihedral_hybrid:dihedrallist");
|
||||
}
|
||||
ndihedrallist[m] = 0;
|
||||
}
|
||||
for (i = 0; i < ndihedrallist_orig; i++) {
|
||||
m = map[dihedrallist_orig[i][4]];
|
||||
n = ndihedrallist[m];
|
||||
dihedrallist[m][n][0] = dihedrallist_orig[i][0];
|
||||
dihedrallist[m][n][1] = dihedrallist_orig[i][1];
|
||||
dihedrallist[m][n][2] = dihedrallist_orig[i][2];
|
||||
dihedrallist[m][n][3] = dihedrallist_orig[i][3];
|
||||
dihedrallist[m][n][4] = dihedrallist_orig[i][4];
|
||||
ndihedrallist[m]++;
|
||||
}
|
||||
}
|
||||
|
||||
// call each sub-style's compute function
|
||||
// must set neighbor->dihedrallist to sub-style dihedrallist before call
|
||||
// accumulate sub-style energy,virial in hybrid's energy,virial
|
||||
|
||||
energy = 0.0;
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (styles[m] == NULL) continue;
|
||||
neighbor->ndihedrallist = ndihedrallist[m];
|
||||
neighbor->dihedrallist = dihedrallist[m];
|
||||
styles[m]->compute(eflag,vflag);
|
||||
if (eflag) {
|
||||
energy += styles[m]->energy;
|
||||
eng_vdwl += styles[m]->eng_vdwl;
|
||||
eng_coul += styles[m]->eng_coul;
|
||||
}
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
|
||||
}
|
||||
|
||||
// restore ptrs to original dihedrallist
|
||||
|
||||
neighbor->ndihedrallist = ndihedrallist_orig;
|
||||
neighbor->dihedrallist = dihedrallist_orig;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
map = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:map");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
|
||||
ndihedrallist = new int[nstyles];
|
||||
maxdihedral = new int[nstyles];
|
||||
dihedrallist = new int**[nstyles];
|
||||
for (int m = 0; m < nstyles; m++) maxdihedral[m] = 0;
|
||||
for (int m = 0; m < nstyles; m++) dihedrallist[m] = NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create one dihedral style for each arg in list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::settings(int narg, char **arg)
|
||||
{
|
||||
nstyles = narg;
|
||||
styles = new Dihedral*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
for (int i = 0; i < m; i++)
|
||||
if (strcmp(arg[m],arg[i]) == 0)
|
||||
error->all("Dihedral style hybrid cannot use same dihedral style twice");
|
||||
if (strcmp(arg[m],"hybrid") == 0)
|
||||
error->all("Dihedral style hybrid cannot have hybrid as an argument");
|
||||
styles[m] = force->new_dihedral(arg[m]);
|
||||
keywords[m] = new char[strlen(arg[m])+1];
|
||||
strcpy(keywords[m],arg[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
// 2nd arg = dihedral style name (harmonic, etc)
|
||||
|
||||
int m;
|
||||
for (m = 0; m < nstyles; m++)
|
||||
if (strcmp(arg[1],keywords[m]) == 0) break;
|
||||
if (m == nstyles) error->all("Dihedral coeff for hybrid has invalid style");
|
||||
|
||||
// set low-level coefficients for each dihedraltype
|
||||
// replace 2nd arg with i, call coeff() with no 1st arg
|
||||
// if sub-style is NULL for "none", still set setflag
|
||||
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
sprintf(arg[1],"%d",i);
|
||||
map[i] = m;
|
||||
if (styles[m]) styles[m]->coeff(which,narg-1,&arg[1]);
|
||||
setflag[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::init_style()
|
||||
{
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) styles[m]->init_style();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&nstyles,sizeof(int),1,fp);
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
n = strlen(keywords[m]) + 1;
|
||||
fwrite(&n,sizeof(int),1,fp);
|
||||
fwrite(keywords[m],sizeof(char),n,fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHybrid::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
int me = comm->me;
|
||||
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
|
||||
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
|
||||
styles = new Dihedral*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
if (me == 0) fread(&n,sizeof(int),1,fp);
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
keywords[m] = new char[n];
|
||||
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
|
||||
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
|
||||
styles[m] = force->new_dihedral(keywords[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int DihedralHybrid::memory_usage()
|
||||
{
|
||||
int bytes = 0;
|
||||
for (int m = 0; m < nstyles; m++) bytes += maxdihedral[m]*5 * sizeof(int);
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) bytes += styles[m]->memory_usage();
|
||||
return bytes;
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_HYBRID_H
|
||||
#define DIHEDRAL_HYBRID_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralHybrid : public Dihedral {
|
||||
public:
|
||||
DihedralHybrid();
|
||||
~DihedralHybrid();
|
||||
void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, int, char **);
|
||||
void init_style();
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
int memory_usage();
|
||||
|
||||
private:
|
||||
int nstyles; // # of different dihedral styles
|
||||
Dihedral **styles; // class list for each Dihedral style
|
||||
char **keywords; // keyword for each dihedral style
|
||||
int *map; // which style each dihedral type points to
|
||||
|
||||
int *ndihedrallist; // # of dihedrals in sub-style dihedrallists
|
||||
int *maxdihedral; // max # of dihedrals sub-style lists can store
|
||||
int ***dihedrallist; // dihedrallist for each sub-style
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,339 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Mathias Puetz (SNL) and friends
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "dihedral_multi_harmonic.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralMultiHarmonic::~DihedralMultiHarmonic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(a1);
|
||||
memory->sfree(a2);
|
||||
memory->sfree(a3);
|
||||
memory->sfree(a4);
|
||||
memory->sfree(a5);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonic::compute(int eflag, int vflag)
|
||||
{
|
||||
int n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z,sb1;
|
||||
double sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx1,sx2,sx12,sy1,sy2,sy12;
|
||||
double sz1,sz2,sz12,s2,sin2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **dihedrallist = neighbor->dihedrallist;
|
||||
int ndihedrallist = neighbor->ndihedrallist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < ndihedrallist; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
if (screen) {
|
||||
fprintf(screen,"Dihedral problem: %d %d %d %d %d %d\n",
|
||||
comm->me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
comm->me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
comm->me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
comm->me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
comm->me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = sum (i=1,5) a_i * c**(i-1)
|
||||
// pd = dp/dc
|
||||
|
||||
p = a1[type] + c*(a2[type] + c*(a3[type] + c*(a4[type] + c*a5[type])));
|
||||
pd = a2[type] + c*(2.0*a3[type] + c*(3.0*a4[type] + c*4.0*a5[type]));
|
||||
|
||||
if (eflag) energy += rfactor * p;
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = (-c*sb1*s1);
|
||||
a22 = sb2*(2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = (-c*sb3*s2);
|
||||
a12 = r12c1*(c1mag*c*s1 + c2mag*s12);
|
||||
a13 = rb1*rb3*s12;
|
||||
a23 = r12c2*(-c2mag*c*s2 - c1mag*s12);
|
||||
|
||||
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
a1 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:a1");
|
||||
a2 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:a2");
|
||||
a3 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:a3");
|
||||
a4 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:a4");
|
||||
a5 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:a5");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonic::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this dihedral style");
|
||||
if (narg != 6) error->all("Incorrect args for dihedral coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
double a1_one = atof(arg[1]);
|
||||
double a2_one = atof(arg[2]);
|
||||
double a3_one = atof(arg[3]);
|
||||
double a4_one = atof(arg[4]);
|
||||
double a5_one = atof(arg[5]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
a1[i] = a1_one;
|
||||
a2[i] = a2_one;
|
||||
a3[i] = a3_one;
|
||||
a4[i] = a4_one;
|
||||
a5[i] = a5_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for dihedral coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&a1[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&a2[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&a3[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&a4[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&a5[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&a1[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&a2[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&a3[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&a4[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&a5[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
MPI_Bcast(&a1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&a2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&a3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&a4[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&a5[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_MULTI_HARMONIC_H
|
||||
#define DIHEDRAL_MULTI_HARMONIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralMultiHarmonic : public Dihedral {
|
||||
public:
|
||||
DihedralMultiHarmonic() {}
|
||||
~DihedralMultiHarmonic();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *a1,*a2,*a3,*a4,*a5;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,349 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Mark Stevens (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "dihedral_opls.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
#define SMALLER 0.00001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
DihedralOPLS::~DihedralOPLS()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k1);
|
||||
memory->sfree(k2);
|
||||
memory->sfree(k3);
|
||||
memory->sfree(k4);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLS::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z,sb1;
|
||||
double sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx1,sx2,sx12,sy1,sy2,sy12;
|
||||
double sz1,sz2,sz12,s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **dihedrallist = neighbor->dihedrallist;
|
||||
int ndihedrallist = neighbor->ndihedrallist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < ndihedrallist; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
cx = vb1y*vb2z - vb1z*vb2y;
|
||||
cy = vb1z*vb2x - vb1x*vb2z;
|
||||
cz = vb1x*vb2y - vb1y*vb2x;
|
||||
cmag = sqrt(cx*cx + cy*cy + cz*cz);
|
||||
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
if (screen) {
|
||||
fprintf(screen,"Dihedral problem: %d %d %d %d %d %d\n",
|
||||
comm->me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
comm->me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
comm->me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
comm->me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
comm->me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = sum (i=1,4) k_i * (1 + (-1)**(i+1)*cos(i*phi) )
|
||||
// pd = dp/dc
|
||||
|
||||
phi = acos(c);
|
||||
if (dx < 0.0) phi *= -1.0;
|
||||
si = sin(phi);
|
||||
if (fabs(si) < SMALLER) si = SMALLER;
|
||||
siinv = 1.0/si;
|
||||
|
||||
p = k1[type]*(1.0 + c) + k2[type]*(1.0 - cos(2.0*phi)) +
|
||||
k3[type]*(1.0 + cos(3.0*phi)) + k4[type]*(1.0 - cos(4.0*phi)) ;
|
||||
pd = k1[type] - 2.0*k2[type]*sin(2.0*phi)*siinv +
|
||||
3.0*k3[type]*sin(3.0*phi)*siinv - 4.0*k4[type]*sin(4.0*phi)*siinv;
|
||||
|
||||
if (eflag) energy += rfactor * p;
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = -c*sb1*s1;
|
||||
a22 = sb2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = -c*sb3*s2;
|
||||
a12 = r12c1 * (c1mag*c*s1 + c2mag*s12);
|
||||
a13 = rb1*rb3*s12;
|
||||
a23 = r12c2 * (-c2mag*c*s2 - c1mag*s12);
|
||||
|
||||
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLS::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ndihedraltypes;
|
||||
|
||||
k1 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k1");
|
||||
k2 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k2");
|
||||
k3 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k3");
|
||||
k4 = (double *) memory->smalloc((n+1)*sizeof(double),"dihedral:k4");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"dihedral:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLS::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this dihedral style");
|
||||
if (narg != 5) error->all("Incorrect args for dihedral coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||
|
||||
double k1_one = atof(arg[1]);
|
||||
double k2_one = atof(arg[2]);
|
||||
double k3_one = atof(arg[3]);
|
||||
double k4_one = atof(arg[4]);
|
||||
|
||||
// store 1/2 factor with prefactor
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k1[i] = 0.5*k1_one;
|
||||
k2[i] = 0.5*k2_one;
|
||||
k3[i] = 0.5*k3_one;
|
||||
k4[i] = 0.5*k4_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for dihedral coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLS::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fwrite(&k4[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLS::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
fread(&k4[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&k2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&k3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&k4[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DIHEDRAL_OPLS_H
|
||||
#define DIHEDRAL_OPLS_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "dihedral.h"
|
||||
|
||||
class DihedralOPLS : public Dihedral {
|
||||
public:
|
||||
DihedralOPLS() {}
|
||||
~DihedralOPLS();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *k1,*k2,*k3,*k4;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,136 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "string.h"
|
||||
#include "dump_bond.h"
|
||||
#include "atom.h"
|
||||
#include "domain.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DumpBond::DumpBond(int narg, char **arg) : Dump(narg, arg)
|
||||
{
|
||||
if (narg != 5) error->all("Illegal dump bond command");
|
||||
if (atom->molecular == 0)
|
||||
error->all("Cannot use dump bond with non-molecular system");
|
||||
|
||||
size_one = 3;
|
||||
|
||||
char *str = "%d %d %d %d";
|
||||
int n = strlen(str) + 1;
|
||||
format_default = new char[n];
|
||||
strcpy(format_default,str);
|
||||
|
||||
// one-time file open
|
||||
|
||||
if (multifile == 0) openfile();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpBond::init()
|
||||
{
|
||||
delete [] format;
|
||||
char *str;
|
||||
if (format_user) str = format_user;
|
||||
else str = format_default;
|
||||
|
||||
int n = strlen(str) + 2;
|
||||
format = new char[n];
|
||||
strcpy(format,str);
|
||||
strcat(format,"\n");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpBond::write_header(int ndump)
|
||||
{
|
||||
fprintf(fp,"ITEM: TIMESTEP\n");
|
||||
fprintf(fp,"%d\n",update->ntimestep);
|
||||
fprintf(fp,"ITEM: NUMBER OF BONDS\n");
|
||||
fprintf(fp,"%d\n",ndump);
|
||||
fprintf(fp,"ITEM: BONDS\n");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int DumpBond::count()
|
||||
{
|
||||
index = 0;
|
||||
|
||||
int *num_bond = atom->num_bond;
|
||||
int **bond_type = atom->bond_type;
|
||||
int **bond_atom = atom->bond_atom;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int i,j,k;
|
||||
|
||||
int m = 0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
for (j = 0; j < num_bond[i]; j++) {
|
||||
k = atom->map(bond_atom[i][j]);
|
||||
if (k >= 0 && !(mask[k] & groupbit)) continue;
|
||||
if (bond_type[i][j] == 0) continue;
|
||||
m++;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int DumpBond::pack()
|
||||
{
|
||||
int *num_bond = atom->num_bond;
|
||||
int **bond_type = atom->bond_type;
|
||||
int **bond_atom = atom->bond_atom;
|
||||
int *tag = atom->tag;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int i,j,k,type,iatom;
|
||||
|
||||
int m = 0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
for (j = 0; j < num_bond[i]; j++) {
|
||||
iatom = bond_atom[i][j];
|
||||
k = atom->map(iatom);
|
||||
if (k >= 0 && !(mask[k] & groupbit)) continue;
|
||||
type = bond_type[i][j];
|
||||
if (type == 0) continue;
|
||||
buf[m++] = type;
|
||||
buf[m++] = tag[i];
|
||||
buf[m++] = iatom;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DumpBond::write_data(int n, double *buf)
|
||||
{
|
||||
int m = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
index++;
|
||||
fprintf(fp,format,
|
||||
index, static_cast<int> (buf[m]),
|
||||
static_cast<int> (buf[m+1]), static_cast<int> (buf[m+2]));
|
||||
m += size_one;
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef DUMP_BOND_H
|
||||
#define DUMP_BOND_H
|
||||
|
||||
#include "dump.h"
|
||||
|
||||
class DumpBond : public Dump {
|
||||
public:
|
||||
DumpBond(int, char **);
|
||||
~DumpBond() {}
|
||||
void init();
|
||||
|
||||
private:
|
||||
int index; // counter for bond output
|
||||
|
||||
void write_header(int);
|
||||
int count();
|
||||
int pack();
|
||||
void write_data(int, double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
846
src/ewald.cpp
846
src/ewald.cpp
@ -1,846 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Roy Pollock (LLNL), Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "math.h"
|
||||
#include "ewald.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "pair_buck_coul_long.h"
|
||||
#include "pair_lj_cut_coul_long.h"
|
||||
#include "pair_lj_charmm_coul_long.h"
|
||||
#include "pair_lj_class2_coul_long.h"
|
||||
#include "pair_table.h"
|
||||
#include "domain.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Ewald::Ewald(int narg, char **arg) : KSpace(narg, arg)
|
||||
{
|
||||
if (narg != 1) error->all("Illegal kspace_style ewald command");
|
||||
|
||||
precision = atof(arg[0]);
|
||||
PI = 4.0*atan(1.0);
|
||||
|
||||
kmax = 0;
|
||||
kxvecs = kyvecs = kzvecs = NULL;
|
||||
ug = NULL;
|
||||
eg = vg = NULL;
|
||||
sfacrl = sfacim = sfacrl_all = sfacim_all = NULL;
|
||||
|
||||
nmax = 0;
|
||||
ek = NULL;
|
||||
cs = sn = NULL;
|
||||
|
||||
kcount = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all memory
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
Ewald::~Ewald()
|
||||
{
|
||||
deallocate();
|
||||
memory->destroy_2d_double_array(ek);
|
||||
memory->destroy_3d_double_array(cs,-kmax_created);
|
||||
memory->destroy_3d_double_array(sn,-kmax_created);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::init()
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
if (screen) fprintf(screen,"Ewald initialization ...\n");
|
||||
if (logfile) fprintf(logfile,"Ewald initialization ...\n");
|
||||
}
|
||||
|
||||
// error check
|
||||
|
||||
if (force->dimension == 2) error->all("Cannot use Ewald with 2d simulation");
|
||||
|
||||
if (slabflag == 0 && domain->nonperiodic > 0)
|
||||
error->all("Cannot use nonperiodic boundaries with Ewald");
|
||||
if (slabflag == 1) {
|
||||
if (domain->xperiodic != 1 || domain->yperiodic != 1 ||
|
||||
domain->boundary[2][0] != 1 || domain->boundary[2][1] != 1)
|
||||
error->all("Incorrect boundaries with slab Ewald");
|
||||
}
|
||||
|
||||
// insure use of pair_style with long-range Coulombics
|
||||
// set cutoff to short-range Coulombic cutoff
|
||||
|
||||
qqrd2e = force->qqrd2e;
|
||||
|
||||
double cutoff;
|
||||
|
||||
Pair *anypair;
|
||||
if (force->pair == NULL)
|
||||
error->all("KSpace style is incompatible with Pair style");
|
||||
else if (anypair = force->pair_match("buck/coul/long"))
|
||||
cutoff = ((PairBuckCoulLong *) anypair)->cut_coul;
|
||||
else if (anypair = force->pair_match("lj/cut/coul/long"))
|
||||
cutoff = ((PairLJCutCoulLong *) anypair)->cut_coul;
|
||||
else if (anypair = force->pair_match("lj/charmm/coul/long"))
|
||||
cutoff = ((PairLJCharmmCoulLong *) anypair)->cut_coul;
|
||||
else if (anypair = force->pair_match("lj/class2/coul/long"))
|
||||
cutoff = ((PairLJClass2CoulLong *) anypair)->cut_coul;
|
||||
else if (anypair = force->pair_match("table"))
|
||||
cutoff = ((PairTable *) anypair)->cut_coul();
|
||||
else error->all("KSpace style is incompatible with Pair style");
|
||||
|
||||
// compute qsum & qsqsum
|
||||
|
||||
double tmp;
|
||||
|
||||
qsum = 0.0;
|
||||
for (int i = 0; i < atom->nlocal; i++) qsum += atom->q[i];
|
||||
MPI_Allreduce(&qsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
qsum = tmp;
|
||||
|
||||
qsqsum = 0.0;
|
||||
for (int i = 0; i < atom->nlocal; i++) qsqsum += atom->q[i]*atom->q[i];
|
||||
MPI_Allreduce(&qsqsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
qsqsum = tmp;
|
||||
|
||||
// setup K-space resolution
|
||||
|
||||
g_ewald = (1.35 - 0.15*log(precision))/cutoff;
|
||||
gsqmx = -4.0*g_ewald*g_ewald*log(precision);
|
||||
|
||||
if (comm->me == 0) {
|
||||
if (screen) fprintf(screen," G vector = %g\n",g_ewald);
|
||||
if (logfile) fprintf(logfile," G vector = %g\n",g_ewald);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
adjust Ewald coeffs, called initially and whenever volume has changed
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::setup()
|
||||
{
|
||||
// volume-dependent factors
|
||||
|
||||
double xprd = domain->xprd;
|
||||
double yprd = domain->yprd;
|
||||
double zprd = domain->zprd;
|
||||
|
||||
// adjustment of z dimension for 2d slab Ewald
|
||||
// 3d Ewald just uses zprd since slab_volfactor = 1.0
|
||||
|
||||
double zprd_slab = zprd*slab_volfactor;
|
||||
volume = xprd * yprd * zprd_slab;
|
||||
|
||||
unitk[0] = 2.0*PI/xprd;
|
||||
unitk[1] = 2.0*PI/yprd;
|
||||
unitk[2] = 2.0*PI/zprd_slab;
|
||||
|
||||
// determine kmax
|
||||
// function of current box size, precision, G_ewald (short-range cutoff)
|
||||
|
||||
int nkxmx = static_cast<int> ((g_ewald*xprd/PI) * sqrt(-log(precision)));
|
||||
int nkymx = static_cast<int> ((g_ewald*yprd/PI) * sqrt(-log(precision)));
|
||||
int nkzmx = static_cast<int> ((g_ewald*zprd_slab/PI) * sqrt(-log(precision)));
|
||||
|
||||
int kmax_old = kmax;
|
||||
kmax = MAX(nkxmx,nkymx);
|
||||
kmax = MAX(kmax,nkzmx);
|
||||
kmax3d = 4*kmax*kmax*kmax + 6*kmax*kmax + 3*kmax;
|
||||
|
||||
// if size has grown, reallocate k-dependent and nlocal-dependent arrays
|
||||
|
||||
if (kmax > kmax_old) {
|
||||
deallocate();
|
||||
allocate();
|
||||
|
||||
memory->destroy_2d_double_array(ek);
|
||||
memory->destroy_3d_double_array(cs,-kmax_created);
|
||||
memory->destroy_3d_double_array(sn,-kmax_created);
|
||||
nmax = atom->nmax;
|
||||
ek = memory->create_2d_double_array(nmax,3,"ewald:ek");
|
||||
cs = memory->create_3d_double_array(-kmax,kmax,3,nmax,"ewald:cs");
|
||||
sn = memory->create_3d_double_array(-kmax,kmax,3,nmax,"ewald:sn");
|
||||
kmax_created = kmax;
|
||||
}
|
||||
|
||||
// pre-compute Ewald coefficients
|
||||
|
||||
int kcount_old = kcount;
|
||||
coeffs();
|
||||
|
||||
// if array sizes changed, print out new sizes
|
||||
|
||||
if (kmax != kmax_old || kcount != kcount_old) {
|
||||
if (comm->me == 0) {
|
||||
if (screen) fprintf(screen," vectors: actual 1d max = %d %d %d\n",
|
||||
kcount,kmax,kmax3d);
|
||||
if (logfile) fprintf(logfile," vectors: actual 1d max = %d %d %d\n",
|
||||
kcount,kmax,kmax3d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute the Ewald long-range force, energy, virial
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,k,n;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
// extend size of nlocal-dependent arrays if necessary
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
if (nlocal > nmax) {
|
||||
memory->destroy_2d_double_array(ek);
|
||||
memory->destroy_3d_double_array(cs,-kmax_created);
|
||||
memory->destroy_3d_double_array(sn,-kmax_created);
|
||||
nmax = atom->nmax;
|
||||
ek = memory->create_2d_double_array(nmax,3,"ewald:ek");
|
||||
cs = memory->create_3d_double_array(-kmax,kmax,3,nmax,"ewald:cs");
|
||||
sn = memory->create_3d_double_array(-kmax,kmax,3,nmax,"ewald:sn");
|
||||
kmax_created = kmax;
|
||||
}
|
||||
|
||||
// partial structure factors on each processor
|
||||
// total structure factor by summing over procs
|
||||
|
||||
eik_dot_r();
|
||||
MPI_Allreduce(sfacrl,sfacrl_all,kcount,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(sfacim,sfacim_all,kcount,MPI_DOUBLE,MPI_SUM,world);
|
||||
|
||||
// K-space portion of electric field
|
||||
// double loop over K-vectors and local atoms
|
||||
|
||||
double **f = atom->f;
|
||||
double *q = atom->q;
|
||||
|
||||
int kx,ky,kz;
|
||||
double cypz,sypz,exprl,expim,partial;
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
ek[i][0] = 0.0;
|
||||
ek[i][1] = 0.0;
|
||||
ek[i][2] = 0.0;
|
||||
}
|
||||
|
||||
for (k = 0; k < kcount; k++) {
|
||||
kx = kxvecs[k];
|
||||
ky = kyvecs[k];
|
||||
kz = kzvecs[k];
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cypz = cs[ky][1][i]*cs[kz][2][i] - sn[ky][1][i]*sn[kz][2][i];
|
||||
sypz = sn[ky][1][i]*cs[kz][2][i] + cs[ky][1][i]*sn[kz][2][i];
|
||||
exprl = cs[kx][0][i]*cypz - sn[kx][0][i]*sypz;
|
||||
expim = sn[kx][0][i]*cypz + cs[kx][0][i]*sypz;
|
||||
partial = expim*sfacrl_all[k] - exprl*sfacim_all[k];
|
||||
ek[i][0] += partial*eg[k][0];
|
||||
ek[i][1] += partial*eg[k][1];
|
||||
ek[i][2] += partial*eg[k][2];
|
||||
}
|
||||
}
|
||||
|
||||
// convert E-field to force
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
f[i][0] += qqrd2e*q[i]*ek[i][0];
|
||||
f[i][1] += qqrd2e*q[i]*ek[i][1];
|
||||
f[i][2] += qqrd2e*q[i]*ek[i][2];
|
||||
}
|
||||
|
||||
// energy if requested
|
||||
|
||||
if (eflag) {
|
||||
for (k = 0; k < kcount; k++)
|
||||
energy += ug[k] * (sfacrl_all[k]*sfacrl_all[k] +
|
||||
sfacim_all[k]*sfacim_all[k]);
|
||||
PI = 4.0*atan(1.0);
|
||||
energy -= g_ewald*qsqsum/1.772453851 +
|
||||
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
|
||||
energy *= qqrd2e;
|
||||
}
|
||||
|
||||
// virial if requested
|
||||
|
||||
if (vflag) {
|
||||
double uk;
|
||||
for (k = 0; k < kcount; k++) {
|
||||
uk = ug[k] * (sfacrl_all[k]*sfacrl_all[k] + sfacim_all[k]*sfacim_all[k]);
|
||||
for (n = 0; n < 6; n++) virial[n] += uk*vg[k][n];
|
||||
}
|
||||
for (n = 0; n < 6; n++) virial[n] *= qqrd2e;
|
||||
}
|
||||
|
||||
if (slabflag) slabcorr(eflag);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::eik_dot_r()
|
||||
{
|
||||
int i,k,l,m,n,ic;
|
||||
double cstr1,sstr1,cstr2,sstr2,cstr3,sstr3,cstr4,sstr4;
|
||||
double sqk,clpm,slpm;
|
||||
|
||||
double **x = atom->x;
|
||||
double *q = atom->q;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
n = 0;
|
||||
|
||||
// (k,0,0), (0,l,0), (0,0,m)
|
||||
|
||||
for (ic = 0; ic < 3; ic++) {
|
||||
sqk = unitk[ic]*unitk[ic];
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cs[0][ic][i] = 1.0;
|
||||
sn[0][ic][i] = 0.0;
|
||||
cs[1][ic][i] = cos(unitk[ic]*x[i][ic]);
|
||||
sn[1][ic][i] = sin(unitk[ic]*x[i][ic]);
|
||||
cs[-1][ic][i] = cs[1][ic][i];
|
||||
sn[-1][ic][i] = -sn[1][ic][i];
|
||||
cstr1 += q[i]*cs[1][ic][i];
|
||||
sstr1 += q[i]*sn[1][ic][i];
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
}
|
||||
}
|
||||
|
||||
for (m = 2; m <= kmax; m++) {
|
||||
for (ic = 0; ic < 3; ic++) {
|
||||
sqk = m*unitk[ic] * m*unitk[ic];
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cs[m][ic][i] = cs[m-1][ic][i]*cs[1][ic][i] -
|
||||
sn[m-1][ic][i]*sn[1][ic][i];
|
||||
sn[m][ic][i] = sn[m-1][ic][i]*cs[1][ic][i] +
|
||||
cs[m-1][ic][i]*sn[1][ic][i];
|
||||
cs[-m][ic][i] = cs[m][ic][i];
|
||||
sn[-m][ic][i] = -sn[m][ic][i];
|
||||
cstr1 += q[i]*cs[m][ic][i];
|
||||
sstr1 += q[i]*sn[m][ic][i];
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,0), 2 = (k,-l,0)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cstr1 += q[i]*(cs[k][0][i]*cs[l][1][i] - sn[k][0][i]*sn[l][1][i]);
|
||||
sstr1 += q[i]*(sn[k][0][i]*cs[l][1][i] + cs[k][0][i]*sn[l][1][i]);
|
||||
cstr2 += q[i]*(cs[k][0][i]*cs[l][1][i] + sn[k][0][i]*sn[l][1][i]);
|
||||
sstr2 += q[i]*(sn[k][0][i]*cs[l][1][i] - cs[k][0][i]*sn[l][1][i]);
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
sfacrl[n] = cstr2;
|
||||
sfacim[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (0,l,m), 2 = (0,l,-m)
|
||||
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (l*unitk[1] * l*unitk[1]) + (m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cstr1 += q[i]*(cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i]);
|
||||
sstr1 += q[i]*(sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i]);
|
||||
cstr2 += q[i]*(cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i]);
|
||||
sstr2 += q[i]*(sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i]);
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
sfacrl[n] = cstr2;
|
||||
sfacim[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,0,m), 2 = (k,0,-m)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
cstr1 += q[i]*(cs[k][0][i]*cs[m][2][i] - sn[k][0][i]*sn[m][2][i]);
|
||||
sstr1 += q[i]*(sn[k][0][i]*cs[m][2][i] + cs[k][0][i]*sn[m][2][i]);
|
||||
cstr2 += q[i]*(cs[k][0][i]*cs[m][2][i] + sn[k][0][i]*sn[m][2][i]);
|
||||
sstr2 += q[i]*(sn[k][0][i]*cs[m][2][i] - cs[k][0][i]*sn[m][2][i]);
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
sfacrl[n] = cstr2;
|
||||
sfacim[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,m), 2 = (k,-l,m), 3 = (k,l,-m), 4 = (k,-l,-m)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]) +
|
||||
(m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
cstr3 = 0.0;
|
||||
sstr3 = 0.0;
|
||||
cstr4 = 0.0;
|
||||
sstr4 = 0.0;
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
|
||||
slpm = sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
|
||||
cstr1 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr1 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
|
||||
slpm = -sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
|
||||
cstr2 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr2 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
|
||||
slpm = sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
|
||||
cstr3 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr3 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
|
||||
slpm = -sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
|
||||
cstr4 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr4 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
}
|
||||
sfacrl[n] = cstr1;
|
||||
sfacim[n++] = sstr1;
|
||||
sfacrl[n] = cstr2;
|
||||
sfacim[n++] = sstr2;
|
||||
sfacrl[n] = cstr3;
|
||||
sfacim[n++] = sstr3;
|
||||
sfacrl[n] = cstr4;
|
||||
sfacim[n++] = sstr4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pre-compute coefficients for each Ewald K-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::coeffs()
|
||||
{
|
||||
int k,l,m;
|
||||
double sqk,vterm;
|
||||
|
||||
double unitkx = unitk[0];
|
||||
double unitky = unitk[1];
|
||||
double unitkz = unitk[2];
|
||||
double g_ewald_sq_inv = 1.0 / (g_ewald*g_ewald);
|
||||
double preu = 4.0*PI/volume;
|
||||
|
||||
kcount = 0;
|
||||
|
||||
// (k,0,0), (0,l,0), (0,0,m)
|
||||
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (m*unitkx) * (m*unitkx);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = m;
|
||||
kyvecs[kcount] = 0;
|
||||
kzvecs[kcount] = 0;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*m*ug[kcount];
|
||||
eg[kcount][1] = 0.0;
|
||||
eg[kcount][2] = 0.0;
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*m)*(unitkx*m);
|
||||
vg[kcount][1] = 1.0;
|
||||
vg[kcount][2] = 1.0;
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
}
|
||||
sqk = (m*unitky) * (m*unitky);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = 0;
|
||||
kyvecs[kcount] = m;
|
||||
kzvecs[kcount] = 0;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 0.0;
|
||||
eg[kcount][1] = 2.0*unitky*m*ug[kcount];
|
||||
eg[kcount][2] = 0.0;
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0;
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*m)*(unitky*m);
|
||||
vg[kcount][2] = 1.0;
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
}
|
||||
sqk = (m*unitkz) * (m*unitkz);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = 0;
|
||||
kyvecs[kcount] = 0;
|
||||
kzvecs[kcount] = m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 0.0;
|
||||
eg[kcount][1] = 0.0;
|
||||
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0;
|
||||
vg[kcount][1] = 1.0;
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,0), 2 = (k,-l,0)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
sqk = (unitkx*k) * (unitkx*k) + (unitky*l) * (unitky*l);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = l;
|
||||
kzvecs[kcount] = 0;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = 0.0;
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0;
|
||||
vg[kcount][3] = vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = -l;
|
||||
kzvecs[kcount] = 0;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = 0.0;
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0;
|
||||
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (0,l,m), 2 = (0,l,-m)
|
||||
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (unitky*l) * (unitky*l) + (unitkz*m) * (unitkz*m);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = 0;
|
||||
kyvecs[kcount] = l;
|
||||
kzvecs[kcount] = m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 0.0;
|
||||
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0;
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = vterm*unitky*l*unitkz*m;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = 0;
|
||||
kyvecs[kcount] = l;
|
||||
kzvecs[kcount] = -m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 0.0;
|
||||
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
|
||||
vg[kcount][0] = 1.0;
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = 0.0;
|
||||
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
|
||||
kcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,0,m), 2 = (k,0,-m)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (unitkx*k) * (unitkx*k) + (unitkz*m) * (unitkz*m);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = 0;
|
||||
kzvecs[kcount] = m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = 0.0;
|
||||
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0;
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = 0;
|
||||
kzvecs[kcount] = -m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = 0.0;
|
||||
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0;
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = 0.0;
|
||||
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = 0.0;
|
||||
kcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,m), 2 = (k,-l,m), 3 = (k,l,-m), 4 = (k,-l,-m)
|
||||
|
||||
for (k = 1; k <= kmax; k++) {
|
||||
for (l = 1; l <= kmax; l++) {
|
||||
for (m = 1; m <= kmax; m++) {
|
||||
sqk = (unitkx*k) * (unitkx*k) + (unitky*l) * (unitky*l) +
|
||||
(unitkz*m) * (unitkz*m);
|
||||
if (sqk <= gsqmx) {
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = l;
|
||||
kzvecs[kcount] = m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
|
||||
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = vterm*unitky*l*unitkz*m;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = -l;
|
||||
kzvecs[kcount] = m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = l;
|
||||
kzvecs[kcount] = -m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
|
||||
kcount++;
|
||||
|
||||
kxvecs[kcount] = k;
|
||||
kyvecs[kcount] = -l;
|
||||
kzvecs[kcount] = -m;
|
||||
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
|
||||
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
|
||||
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
|
||||
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
|
||||
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
|
||||
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
|
||||
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
|
||||
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
|
||||
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
|
||||
vg[kcount][5] = vterm*unitky*l*unitkz*m;
|
||||
kcount++;;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate memory that depends on # of K-vectors
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::allocate()
|
||||
{
|
||||
kxvecs = new int[kmax3d];
|
||||
kyvecs = new int[kmax3d];
|
||||
kzvecs = new int[kmax3d];
|
||||
|
||||
ug = new double[kmax3d];
|
||||
eg = memory->create_2d_double_array(kmax3d,3,"ewald:eg");
|
||||
vg = memory->create_2d_double_array(kmax3d,6,"ewald:vg");
|
||||
|
||||
sfacrl = new double[kmax3d];
|
||||
sfacim = new double[kmax3d];
|
||||
sfacrl_all = new double[kmax3d];
|
||||
sfacim_all = new double[kmax3d];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
deallocate memory that depends on # of K-vectors
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::deallocate()
|
||||
{
|
||||
delete [] kxvecs;
|
||||
delete [] kyvecs;
|
||||
delete [] kzvecs;
|
||||
|
||||
delete [] ug;
|
||||
memory->destroy_2d_double_array(eg);
|
||||
memory->destroy_2d_double_array(vg);
|
||||
|
||||
delete [] sfacrl;
|
||||
delete [] sfacim;
|
||||
delete [] sfacrl_all;
|
||||
delete [] sfacim_all;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Slab-geometry correction term to dampen inter-slab interactions between
|
||||
periodically repeating slabs. Yields good approximation to 2-D Ewald if
|
||||
adequate empty space is left between repeating slabs (J. Chem. Phys.
|
||||
111, 3155). Slabs defined here to be parallel to the xy plane.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Ewald::slabcorr(int eflag)
|
||||
{
|
||||
// compute local contribution to global dipole moment
|
||||
|
||||
double *q = atom->q;
|
||||
double **x = atom->x;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
double dipole = 0.0;
|
||||
for (int i = 0; i < nlocal; i++) dipole += q[i]*x[i][2];
|
||||
|
||||
// sum local contributions to get global dipole moment
|
||||
|
||||
double dipole_all;
|
||||
MPI_Allreduce(&dipole,&dipole_all,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
|
||||
// compute corrections
|
||||
|
||||
double e_slabcorr = 2.0*PI*dipole_all*dipole_all/volume;
|
||||
|
||||
if (eflag) energy += qqrd2e*e_slabcorr;
|
||||
|
||||
// add on force corrections
|
||||
|
||||
double ffact = -4.0*PI*dipole_all/volume;
|
||||
double **f = atom->f;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) f[i][2] += qqrd2e*q[i]*ffact;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int Ewald::memory_usage()
|
||||
{
|
||||
int bytes = 3 * kmax3d * sizeof(int);
|
||||
bytes += (1 + 3 + 6) * kmax3d * sizeof(double);
|
||||
bytes += 4 * kmax3d * sizeof(double);
|
||||
bytes += nmax*3 * sizeof(double);
|
||||
bytes += 2 * (2*kmax+1)*3*nmax * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
52
src/ewald.h
52
src/ewald.h
@ -1,52 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef EWALD_H
|
||||
#define EWALD_H
|
||||
|
||||
#include "kspace.h"
|
||||
|
||||
class Ewald : public KSpace {
|
||||
public:
|
||||
Ewald(int, char **);
|
||||
~Ewald();
|
||||
void init();
|
||||
void setup();
|
||||
void compute(int, int);
|
||||
int memory_usage();
|
||||
|
||||
private:
|
||||
double PI;
|
||||
double precision;
|
||||
int kcount,kmax,kmax3d,kmax_created;
|
||||
double qqrd2e;
|
||||
double gsqmx,qsum,qsqsum,volume;
|
||||
int nmax;
|
||||
|
||||
double unitk[3];
|
||||
int *kxvecs,*kyvecs,*kzvecs;
|
||||
double *ug;
|
||||
double **eg,**vg;
|
||||
double **ek;
|
||||
double *sfacrl,*sfacim,*sfacrl_all,*sfacim_all;
|
||||
double ***cs,***sn;
|
||||
|
||||
void eik_dot_r();
|
||||
void coeffs();
|
||||
void allocate();
|
||||
void deallocate();
|
||||
void slabcorr(int);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
999
src/fft3d.cpp
999
src/fft3d.cpp
@ -1,999 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Jim Shepherd (GA Tech) added SGI SCSL support
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "math.h"
|
||||
#include "fft3d.h"
|
||||
#include "remap.h"
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Data layout for 3d FFTs:
|
||||
|
||||
data set of Nfast x Nmid x Nslow elements is owned by P procs
|
||||
on input, each proc owns a subsection of the elements
|
||||
on output, each proc will own a (possibly different) subsection
|
||||
my subsection must not overlap with any other proc's subsection,
|
||||
i.e. the union of all proc's input (or output) subsections must
|
||||
exactly tile the global Nfast x Nmid x Nslow data set
|
||||
when called from C, all subsection indices are
|
||||
C-style from 0 to N-1 where N = Nfast or Nmid or Nslow
|
||||
when called from F77, all subsection indices are
|
||||
F77-style from 1 to N where N = Nfast or Nmid or Nslow
|
||||
a proc can own 0 elements on input or output
|
||||
by specifying hi index < lo index
|
||||
on both input and output, data is stored contiguously on a processor
|
||||
with a fast-varying, mid-varying, and slow-varying index
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Perform 3d FFT
|
||||
|
||||
Arguments:
|
||||
in starting address of input data on this proc
|
||||
out starting address of where output data for this proc
|
||||
will be placed (can be same as in)
|
||||
flag 1 for forward FFT, -1 for inverse FFT
|
||||
plan plan returned by previous call to fft_3d_create_plan
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan)
|
||||
{
|
||||
int i,total,length,offset,num;
|
||||
double norm;
|
||||
FFT_DATA *data,*copy;
|
||||
|
||||
// system specific constants
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
int isys = 0;
|
||||
FFT_PREC scalef = 1.0;
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
char c = 'C';
|
||||
char f = 'F';
|
||||
char b = 'B';
|
||||
int one = 1;
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
int isys = 0;
|
||||
double scalef = 1.0;
|
||||
#endif
|
||||
|
||||
// pre-remap to prepare for 1st FFTs if needed
|
||||
// copy = loc for remap result
|
||||
|
||||
if (plan->pre_plan) {
|
||||
if (plan->pre_target == 0) copy = out;
|
||||
else copy = plan->copy;
|
||||
remap_3d((double *) in, (double *) copy, (double *) plan->scratch,
|
||||
plan->pre_plan);
|
||||
data = copy;
|
||||
}
|
||||
else
|
||||
data = in;
|
||||
|
||||
// 1d FFTs along fast axis
|
||||
|
||||
total = plan->total1;
|
||||
length = plan->length1;
|
||||
|
||||
#ifdef FFT_SGI
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,&data[offset],1,plan->coeff1);
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff1,
|
||||
plan->work1,&isys);
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&data[offset],&length,&flag,plan->coeff1);
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
if (flag == -1)
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one);
|
||||
else
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one);
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff1,
|
||||
plan->work1,&isys);
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
if (flag == -1)
|
||||
fftw(plan->plan_fast_forward,total/length,data,1,length,NULL,0,0);
|
||||
else
|
||||
fftw(plan->plan_fast_backward,total/length,data,1,length,NULL,0,0);
|
||||
#endif
|
||||
|
||||
// 1st mid-remap to prepare for 2nd FFTs
|
||||
// copy = loc for remap result
|
||||
|
||||
if (plan->mid1_target == 0) copy = out;
|
||||
else copy = plan->copy;
|
||||
remap_3d((double *) data, (double *) copy, (double *) plan->scratch,
|
||||
plan->mid1_plan);
|
||||
data = copy;
|
||||
|
||||
// 1d FFTs along mid axis
|
||||
|
||||
total = plan->total2;
|
||||
length = plan->length2;
|
||||
|
||||
#ifdef FFT_SGI
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,&data[offset],1,plan->coeff2);
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff2,
|
||||
plan->work2,&isys);
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&data[offset],&length,&flag,plan->coeff2);
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
if (flag == -1)
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one);
|
||||
else
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one);
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff2,
|
||||
plan->work2,&isys);
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
if (flag == -1)
|
||||
fftw(plan->plan_mid_forward,total/length,data,1,length,NULL,0,0);
|
||||
else
|
||||
fftw(plan->plan_mid_backward,total/length,data,1,length,NULL,0,0);
|
||||
#endif
|
||||
|
||||
// 2nd mid-remap to prepare for 3rd FFTs
|
||||
// copy = loc for remap result
|
||||
|
||||
if (plan->mid2_target == 0) copy = out;
|
||||
else copy = plan->copy;
|
||||
remap_3d((double *) data, (double *) copy, (double *) plan->scratch,
|
||||
plan->mid2_plan);
|
||||
data = copy;
|
||||
|
||||
// 1d FFTs along slow axis
|
||||
|
||||
total = plan->total3;
|
||||
length = plan->length3;
|
||||
|
||||
#ifdef FFT_SGI
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,&data[offset],1,plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff3,
|
||||
plan->work3,&isys);
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&data[offset],&length,&flag,plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
if (flag == -1)
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one);
|
||||
else
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one);
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
for (offset = 0; offset < total; offset += length)
|
||||
FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff3,
|
||||
plan->work3,&isys);
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
if (flag == -1)
|
||||
fftw(plan->plan_slow_forward,total/length,data,1,length,NULL,0,0);
|
||||
else
|
||||
fftw(plan->plan_slow_backward,total/length,data,1,length,NULL,0,0);
|
||||
#endif
|
||||
|
||||
// post-remap to put data in output format if needed
|
||||
// destination is always out
|
||||
|
||||
if (plan->post_plan)
|
||||
remap_3d((double *) data, (double *) out, (double *) plan->scratch,
|
||||
plan->post_plan);
|
||||
|
||||
// scaling if required
|
||||
|
||||
#ifndef FFT_T3E
|
||||
if (flag == 1 && plan->scaled) {
|
||||
norm = plan->norm;
|
||||
num = plan->normnum;
|
||||
for (i = 0; i < num; i++) {
|
||||
out[i].re *= norm;
|
||||
out[i].im *= norm;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_T3E
|
||||
if (flag == 1 && plan->scaled) {
|
||||
norm = plan->norm;
|
||||
num = plan->normnum;
|
||||
for (i = 0; i < num; i++) out[i] *= (norm,norm);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Create plan for performing a 3d FFT
|
||||
|
||||
Arguments:
|
||||
comm MPI communicator for the P procs which own the data
|
||||
nfast,nmid,nslow size of global 3d matrix
|
||||
in_ilo,in_ihi input bounds of data I own in fast index
|
||||
in_jlo,in_jhi input bounds of data I own in mid index
|
||||
in_klo,in_khi input bounds of data I own in slow index
|
||||
out_ilo,out_ihi output bounds of data I own in fast index
|
||||
out_jlo,out_jhi output bounds of data I own in mid index
|
||||
out_klo,out_khi output bounds of data I own in slow index
|
||||
scaled 0 = no scaling of result, 1 = scaling
|
||||
permute permutation in storage order of indices on output
|
||||
0 = no permutation
|
||||
1 = permute once = mid->fast, slow->mid, fast->slow
|
||||
2 = permute twice = slow->fast, fast->mid, mid->slow
|
||||
nbuf returns size of internal storage buffers used by FFT
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
struct fft_plan_3d *fft_3d_create_plan(
|
||||
MPI_Comm comm, int nfast, int nmid, int nslow,
|
||||
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
|
||||
int in_klo, int in_khi,
|
||||
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
|
||||
int out_klo, int out_khi,
|
||||
int scaled, int permute, int *nbuf)
|
||||
{
|
||||
struct fft_plan_3d *plan;
|
||||
int me,nprocs;
|
||||
int i,num,flag,remapflag,fftflag;
|
||||
int first_ilo,first_ihi,first_jlo,first_jhi,first_klo,first_khi;
|
||||
int second_ilo,second_ihi,second_jlo,second_jhi,second_klo,second_khi;
|
||||
int third_ilo,third_ihi,third_jlo,third_jhi,third_klo,third_khi;
|
||||
int out_size,first_size,second_size,third_size,copy_size,scratch_size;
|
||||
int np1,np2,ip1,ip2;
|
||||
int list[50];
|
||||
|
||||
// system specific variables
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
FFT_DATA dummy_d[5];
|
||||
FFT_PREC dummy_p[5];
|
||||
int isign,isys;
|
||||
FFT_PREC scalef;
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
FFT_DATA dummy;
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
FFT_DATA dummy[5];
|
||||
int isign,isys;
|
||||
double scalef;
|
||||
#endif
|
||||
|
||||
// query MPI info
|
||||
|
||||
MPI_Comm_rank(comm,&me);
|
||||
MPI_Comm_size(comm,&nprocs);
|
||||
|
||||
#ifdef FFT_NONE
|
||||
if (me == 0) {
|
||||
printf("ERROR: Cannot use FFTs with FFT_NONE set\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// compute division of procs in 2 dimensions not on-processor
|
||||
|
||||
bifactor(nprocs,&np1,&np2);
|
||||
ip1 = me % np1;
|
||||
ip2 = me/np1;
|
||||
|
||||
// allocate memory for plan data struct
|
||||
|
||||
plan = (struct fft_plan_3d *) malloc(sizeof(struct fft_plan_3d));
|
||||
if (plan == NULL) return NULL;
|
||||
|
||||
// remap from initial distribution to layout needed for 1st set of 1d FFTs
|
||||
// not needed if all procs own entire fast axis initially
|
||||
// first indices = distribution after 1st set of FFTs
|
||||
|
||||
if (in_ilo == 0 && in_ihi == nfast-1)
|
||||
flag = 0;
|
||||
else
|
||||
flag = 1;
|
||||
|
||||
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
|
||||
|
||||
if (remapflag == 0) {
|
||||
first_ilo = in_ilo;
|
||||
first_ihi = in_ihi;
|
||||
first_jlo = in_jlo;
|
||||
first_jhi = in_jhi;
|
||||
first_klo = in_klo;
|
||||
first_khi = in_khi;
|
||||
plan->pre_plan = NULL;
|
||||
}
|
||||
else {
|
||||
first_ilo = 0;
|
||||
first_ihi = nfast - 1;
|
||||
first_jlo = ip1*nmid/np1;
|
||||
first_jhi = (ip1+1)*nmid/np1 - 1;
|
||||
first_klo = ip2*nslow/np2;
|
||||
first_khi = (ip2+1)*nslow/np2 - 1;
|
||||
plan->pre_plan =
|
||||
remap_3d_create_plan(comm,in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
|
||||
first_ilo,first_ihi,first_jlo,first_jhi,
|
||||
first_klo,first_khi,
|
||||
FFT_PRECISION,0,0,2);
|
||||
if (plan->pre_plan == NULL) return NULL;
|
||||
}
|
||||
|
||||
// 1d FFTs along fast axis
|
||||
|
||||
plan->length1 = nfast;
|
||||
plan->total1 = nfast * (first_jhi-first_jlo+1) * (first_khi-first_klo+1);
|
||||
|
||||
// remap from 1st to 2nd FFT
|
||||
// choose which axis is split over np1 vs np2 to minimize communication
|
||||
// second indices = distribution after 2nd set of FFTs
|
||||
|
||||
second_ilo = ip1*nfast/np1;
|
||||
second_ihi = (ip1+1)*nfast/np1 - 1;
|
||||
second_jlo = 0;
|
||||
second_jhi = nmid - 1;
|
||||
second_klo = ip2*nslow/np2;
|
||||
second_khi = (ip2+1)*nslow/np2 - 1;
|
||||
plan->mid1_plan =
|
||||
remap_3d_create_plan(comm,
|
||||
first_ilo,first_ihi,first_jlo,first_jhi,
|
||||
first_klo,first_khi,
|
||||
second_ilo,second_ihi,second_jlo,second_jhi,
|
||||
second_klo,second_khi,
|
||||
FFT_PRECISION,1,0,2);
|
||||
if (plan->mid1_plan == NULL) return NULL;
|
||||
|
||||
// 1d FFTs along mid axis
|
||||
|
||||
plan->length2 = nmid;
|
||||
plan->total2 = (second_ihi-second_ilo+1) * nmid * (second_khi-second_klo+1);
|
||||
|
||||
// remap from 2nd to 3rd FFT
|
||||
// if final distribution is permute=2 with all procs owning entire slow axis
|
||||
// then this remapping goes directly to final distribution
|
||||
// third indices = distribution after 3rd set of FFTs
|
||||
|
||||
if (permute == 2 && out_klo == 0 && out_khi == nslow-1)
|
||||
flag = 0;
|
||||
else
|
||||
flag = 1;
|
||||
|
||||
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
|
||||
|
||||
if (remapflag == 0) {
|
||||
third_ilo = out_ilo;
|
||||
third_ihi = out_ihi;
|
||||
third_jlo = out_jlo;
|
||||
third_jhi = out_jhi;
|
||||
third_klo = out_klo;
|
||||
third_khi = out_khi;
|
||||
}
|
||||
else {
|
||||
third_ilo = ip1*nfast/np1;
|
||||
third_ihi = (ip1+1)*nfast/np1 - 1;
|
||||
third_jlo = ip2*nmid/np2;
|
||||
third_jhi = (ip2+1)*nmid/np2 - 1;
|
||||
third_klo = 0;
|
||||
third_khi = nslow - 1;
|
||||
}
|
||||
|
||||
plan->mid2_plan =
|
||||
remap_3d_create_plan(comm,
|
||||
second_jlo,second_jhi,second_klo,second_khi,
|
||||
second_ilo,second_ihi,
|
||||
third_jlo,third_jhi,third_klo,third_khi,
|
||||
third_ilo,third_ihi,
|
||||
FFT_PRECISION,1,0,2);
|
||||
if (plan->mid2_plan == NULL) return NULL;
|
||||
|
||||
// 1d FFTs along slow axis
|
||||
|
||||
plan->length3 = nslow;
|
||||
plan->total3 = (third_ihi-third_ilo+1) * (third_jhi-third_jlo+1) * nslow;
|
||||
|
||||
// remap from 3rd FFT to final distribution
|
||||
// not needed if permute = 2 and third indices = out indices on all procs
|
||||
|
||||
if (permute == 2 &&
|
||||
out_ilo == third_ilo && out_ihi == third_ihi &&
|
||||
out_jlo == third_jlo && out_jhi == third_jhi &&
|
||||
out_klo == third_klo && out_khi == third_khi)
|
||||
flag = 0;
|
||||
else
|
||||
flag = 1;
|
||||
|
||||
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
|
||||
|
||||
if (remapflag == 0)
|
||||
plan->post_plan = NULL;
|
||||
else {
|
||||
plan->post_plan =
|
||||
remap_3d_create_plan(comm,
|
||||
third_klo,third_khi,third_ilo,third_ihi,
|
||||
third_jlo,third_jhi,
|
||||
out_klo,out_khi,out_ilo,out_ihi,
|
||||
out_jlo,out_jhi,
|
||||
FFT_PRECISION,(permute+1)%3,0,2);
|
||||
if (plan->post_plan == NULL) return NULL;
|
||||
}
|
||||
|
||||
// configure plan memory pointers and allocate work space
|
||||
// out_size = amount of memory given to FFT by user
|
||||
// first/second/third_size = amount of memory needed after pre,mid1,mid2 remaps
|
||||
// copy_size = amount needed internally for extra copy of data
|
||||
// scratch_size = amount needed internally for remap scratch space
|
||||
// for each remap:
|
||||
// out space used for result if big enough, else require copy buffer
|
||||
// accumulate largest required remap scratch space
|
||||
|
||||
out_size = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) * (out_khi-out_klo+1);
|
||||
first_size = (first_ihi-first_ilo+1) * (first_jhi-first_jlo+1) *
|
||||
(first_khi-first_klo+1);
|
||||
second_size = (second_ihi-second_ilo+1) * (second_jhi-second_jlo+1) *
|
||||
(second_khi-second_klo+1);
|
||||
third_size = (third_ihi-third_ilo+1) * (third_jhi-third_jlo+1) *
|
||||
(third_khi-third_klo+1);
|
||||
|
||||
copy_size = 0;
|
||||
scratch_size = 0;
|
||||
|
||||
if (plan->pre_plan) {
|
||||
if (first_size <= out_size)
|
||||
plan->pre_target = 0;
|
||||
else {
|
||||
plan->pre_target = 1;
|
||||
copy_size = MAX(copy_size,first_size);
|
||||
}
|
||||
scratch_size = MAX(scratch_size,first_size);
|
||||
}
|
||||
|
||||
if (plan->mid1_plan) {
|
||||
if (second_size <= out_size)
|
||||
plan->mid1_target = 0;
|
||||
else {
|
||||
plan->mid1_target = 1;
|
||||
copy_size = MAX(copy_size,second_size);
|
||||
}
|
||||
scratch_size = MAX(scratch_size,second_size);
|
||||
}
|
||||
|
||||
if (plan->mid2_plan) {
|
||||
if (third_size <= out_size)
|
||||
plan->mid2_target = 0;
|
||||
else {
|
||||
plan->mid2_target = 1;
|
||||
copy_size = MAX(copy_size,third_size);
|
||||
}
|
||||
scratch_size = MAX(scratch_size,third_size);
|
||||
}
|
||||
|
||||
if (plan->post_plan)
|
||||
scratch_size = MAX(scratch_size,out_size);
|
||||
|
||||
*nbuf = copy_size + scratch_size;
|
||||
|
||||
if (copy_size) {
|
||||
plan->copy = (FFT_DATA *) malloc(copy_size*sizeof(FFT_DATA));
|
||||
if (plan->copy == NULL) return NULL;
|
||||
}
|
||||
else plan->copy = NULL;
|
||||
|
||||
if (scratch_size) {
|
||||
plan->scratch = (FFT_DATA *) malloc(scratch_size*sizeof(FFT_DATA));
|
||||
if (plan->scratch == NULL) return NULL;
|
||||
}
|
||||
else plan->scratch = NULL;
|
||||
|
||||
// system specific pre-computation of 1d FFT coeffs
|
||||
// and scaling normalization
|
||||
|
||||
#ifdef FFT_SGI
|
||||
|
||||
plan->coeff1 = (FFT_DATA *) malloc((nfast+15)*sizeof(FFT_DATA));
|
||||
plan->coeff2 = (FFT_DATA *) malloc((nmid+15)*sizeof(FFT_DATA));
|
||||
plan->coeff3 = (FFT_DATA *) malloc((nslow+15)*sizeof(FFT_DATA));
|
||||
|
||||
if (plan->coeff1 == NULL || plan->coeff2 == NULL ||
|
||||
plan->coeff3 == NULL) return NULL;
|
||||
|
||||
FFT_1D_INIT(nfast,plan->coeff1);
|
||||
FFT_1D_INIT(nmid,plan->coeff2);
|
||||
FFT_1D_INIT(nslow,plan->coeff3);
|
||||
|
||||
if (scaled == 0)
|
||||
plan->scaled = 0;
|
||||
else {
|
||||
plan->scaled = 1;
|
||||
plan->norm = 1.0/(nfast*nmid*nslow);
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
|
||||
plan->coeff1 = (FFT_PREC *) malloc((2*nfast+30)*sizeof(FFT_PREC));
|
||||
plan->coeff2 = (FFT_PREC *) malloc((2*nmid+30)*sizeof(FFT_PREC));
|
||||
plan->coeff3 = (FFT_PREC *) malloc((2*nslow+30)*sizeof(FFT_PREC));
|
||||
|
||||
if (plan->coeff1 == NULL || plan->coeff2 == NULL ||
|
||||
plan->coeff3 == NULL) return NULL;
|
||||
|
||||
plan->work1 = (FFT_PREC *) malloc((2*nfast)*sizeof(FFT_PREC));
|
||||
plan->work2 = (FFT_PREC *) malloc((2*nmid)*sizeof(FFT_PREC));
|
||||
plan->work3 = (FFT_PREC *) malloc((2*nslow)*sizeof(FFT_PREC));
|
||||
|
||||
if (plan->work1 == NULL || plan->work2 == NULL ||
|
||||
plan->work3 == NULL) return NULL;
|
||||
|
||||
isign = 0;
|
||||
scalef = 1.0;
|
||||
isys = 0;
|
||||
|
||||
FFT_1D_INIT(isign,nfast,scalef,dummy_d,dummy_d,plan->coeff1,dummy_p,&isys);
|
||||
FFT_1D_INIT(isign,nmid,scalef,dummy_d,dummy_d,plan->coeff2,dummy_p,&isys);
|
||||
FFT_1D_INIT(isign,nslow,scalef,dummy_d,dummy_d,plan->coeff3,dummy_p,&isys);
|
||||
|
||||
if (scaled == 0)
|
||||
plan->scaled = 0;
|
||||
else {
|
||||
plan->scaled = 1;
|
||||
plan->norm = 1.0/(nfast*nmid*nslow);
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_INTEL
|
||||
|
||||
flag = 0;
|
||||
|
||||
num = 0;
|
||||
factor(nfast,&num,list);
|
||||
for (i = 0; i < num; i++)
|
||||
if (list[i] != 2 && list[i] != 3 && list[i] != 5) flag = 1;
|
||||
num = 0;
|
||||
factor(nmid,&num,list);
|
||||
for (i = 0; i < num; i++)
|
||||
if (list[i] != 2 && list[i] != 3 && list[i] != 5) flag = 1;
|
||||
num = 0;
|
||||
factor(nslow,&num,list);
|
||||
for (i = 0; i < num; i++)
|
||||
if (list[i] != 2 && list[i] != 3 && list[i] != 5) flag = 1;
|
||||
|
||||
MPI_Allreduce(&flag,&fftflag,1,MPI_INT,MPI_MAX,comm);
|
||||
if (fftflag) {
|
||||
if (me == 0) printf("ERROR: FFTs are not power of 2,3,5\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
plan->coeff1 = (FFT_DATA *) malloc((3*nfast/2+1)*sizeof(FFT_DATA));
|
||||
plan->coeff2 = (FFT_DATA *) malloc((3*nmid/2+1)*sizeof(FFT_DATA));
|
||||
plan->coeff3 = (FFT_DATA *) malloc((3*nslow/2+1)*sizeof(FFT_DATA));
|
||||
|
||||
if (plan->coeff1 == NULL || plan->coeff2 == NULL ||
|
||||
plan->coeff3 == NULL) return NULL;
|
||||
|
||||
flag = 0;
|
||||
FFT_1D_INIT(&dummy,&nfast,&flag,plan->coeff1);
|
||||
FFT_1D_INIT(&dummy,&nmid,&flag,plan->coeff2);
|
||||
FFT_1D_INIT(&dummy,&nslow,&flag,plan->coeff3);
|
||||
|
||||
if (scaled == 0) {
|
||||
plan->scaled = 1;
|
||||
plan->norm = nfast*nmid*nslow;
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
else
|
||||
plan->scaled = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_DEC
|
||||
|
||||
if (scaled == 0) {
|
||||
plan->scaled = 1;
|
||||
plan->norm = nfast*nmid*nslow;
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
else
|
||||
plan->scaled = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_T3E
|
||||
|
||||
plan->coeff1 = (double *) malloc((12*nfast)*sizeof(double));
|
||||
plan->coeff2 = (double *) malloc((12*nmid)*sizeof(double));
|
||||
plan->coeff3 = (double *) malloc((12*nslow)*sizeof(double));
|
||||
|
||||
if (plan->coeff1 == NULL || plan->coeff2 == NULL ||
|
||||
plan->coeff3 == NULL) return NULL;
|
||||
|
||||
plan->work1 = (double *) malloc((8*nfast)*sizeof(double));
|
||||
plan->work2 = (double *) malloc((8*nmid)*sizeof(double));
|
||||
plan->work3 = (double *) malloc((8*nslow)*sizeof(double));
|
||||
|
||||
if (plan->work1 == NULL || plan->work2 == NULL ||
|
||||
plan->work3 == NULL) return NULL;
|
||||
|
||||
isign = 0;
|
||||
scalef = 1.0;
|
||||
isys = 0;
|
||||
|
||||
FFT_1D_INIT(&isign,&nfast,&scalef,dummy,dummy,plan->coeff1,dummy,&isys);
|
||||
FFT_1D_INIT(&isign,&nmid,&scalef,dummy,dummy,plan->coeff2,dummy,&isys);
|
||||
FFT_1D_INIT(&isign,&nslow,&scalef,dummy,dummy,plan->coeff3,dummy,&isys);
|
||||
|
||||
if (scaled == 0)
|
||||
plan->scaled = 0;
|
||||
else {
|
||||
plan->scaled = 1;
|
||||
plan->norm = 1.0/(nfast*nmid*nslow);
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_FFTW
|
||||
|
||||
plan->plan_fast_forward =
|
||||
fftw_create_plan(nfast,FFTW_FORWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
plan->plan_fast_backward =
|
||||
fftw_create_plan(nfast,FFTW_BACKWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
|
||||
if (nmid == nfast) {
|
||||
plan->plan_mid_forward = plan->plan_fast_forward;
|
||||
plan->plan_mid_backward = plan->plan_fast_backward;
|
||||
}
|
||||
else {
|
||||
plan->plan_mid_forward =
|
||||
fftw_create_plan(nmid,FFTW_FORWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
plan->plan_mid_backward =
|
||||
fftw_create_plan(nmid,FFTW_BACKWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
}
|
||||
|
||||
if (nslow == nfast) {
|
||||
plan->plan_slow_forward = plan->plan_fast_forward;
|
||||
plan->plan_slow_backward = plan->plan_fast_backward;
|
||||
}
|
||||
else if (nslow == nmid) {
|
||||
plan->plan_slow_forward = plan->plan_mid_forward;
|
||||
plan->plan_slow_backward = plan->plan_mid_backward;
|
||||
}
|
||||
else {
|
||||
plan->plan_slow_forward =
|
||||
fftw_create_plan(nslow,FFTW_FORWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
plan->plan_slow_backward =
|
||||
fftw_create_plan(nslow,FFTW_BACKWARD,FFTW_ESTIMATE | FFTW_IN_PLACE);
|
||||
}
|
||||
|
||||
if (scaled == 0)
|
||||
plan->scaled = 0;
|
||||
else {
|
||||
plan->scaled = 1;
|
||||
plan->norm = 1.0/(nfast*nmid*nslow);
|
||||
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Destroy a 3d fft plan
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void fft_3d_destroy_plan(struct fft_plan_3d *plan)
|
||||
{
|
||||
if (plan->pre_plan) remap_3d_destroy_plan(plan->pre_plan);
|
||||
if (plan->mid1_plan) remap_3d_destroy_plan(plan->mid1_plan);
|
||||
if (plan->mid2_plan) remap_3d_destroy_plan(plan->mid2_plan);
|
||||
if (plan->post_plan) remap_3d_destroy_plan(plan->post_plan);
|
||||
|
||||
if (plan->copy) free(plan->copy);
|
||||
if (plan->scratch) free(plan->scratch);
|
||||
|
||||
#ifdef FFT_SGI
|
||||
free(plan->coeff1);
|
||||
free(plan->coeff2);
|
||||
free(plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
free(plan->coeff1);
|
||||
free(plan->coeff2);
|
||||
free(plan->coeff3);
|
||||
free(plan->work1);
|
||||
free(plan->work2);
|
||||
free(plan->work3);
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
free(plan->coeff1);
|
||||
free(plan->coeff2);
|
||||
free(plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
free(plan->coeff1);
|
||||
free(plan->coeff2);
|
||||
free(plan->coeff3);
|
||||
free(plan->work1);
|
||||
free(plan->work2);
|
||||
free(plan->work3);
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
if (plan->plan_slow_forward != plan->plan_mid_forward &&
|
||||
plan->plan_slow_forward != plan->plan_fast_forward) {
|
||||
fftw_destroy_plan(plan->plan_slow_forward);
|
||||
fftw_destroy_plan(plan->plan_slow_backward);
|
||||
}
|
||||
if (plan->plan_mid_forward != plan->plan_fast_forward) {
|
||||
fftw_destroy_plan(plan->plan_mid_forward);
|
||||
fftw_destroy_plan(plan->plan_mid_backward);
|
||||
}
|
||||
fftw_destroy_plan(plan->plan_fast_forward);
|
||||
fftw_destroy_plan(plan->plan_fast_backward);
|
||||
#endif
|
||||
|
||||
free(plan);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
recursively divide n into small factors, return them in list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void factor(int n, int *num, int *list)
|
||||
{
|
||||
if (n == 1) {
|
||||
return;
|
||||
}
|
||||
else if (n % 2 == 0) {
|
||||
*list = 2;
|
||||
(*num)++;
|
||||
factor(n/2,num,list+1);
|
||||
}
|
||||
else if (n % 3 == 0) {
|
||||
*list = 3;
|
||||
(*num)++;
|
||||
factor(n/3,num,list+1);
|
||||
}
|
||||
else if (n % 5 == 0) {
|
||||
*list = 5;
|
||||
(*num)++;
|
||||
factor(n/5,num,list+1);
|
||||
}
|
||||
else if (n % 7 == 0) {
|
||||
*list = 7;
|
||||
(*num)++;
|
||||
factor(n/7,num,list+1);
|
||||
}
|
||||
else if (n % 11 == 0) {
|
||||
*list = 11;
|
||||
(*num)++;
|
||||
factor(n/11,num,list+1);
|
||||
}
|
||||
else if (n % 13 == 0) {
|
||||
*list = 13;
|
||||
(*num)++;
|
||||
factor(n/13,num,list+1);
|
||||
}
|
||||
else {
|
||||
*list = n;
|
||||
(*num)++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
divide n into 2 factors of as equal size as possible
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void bifactor(int n, int *factor1, int *factor2)
|
||||
{
|
||||
int n1,n2,facmax;
|
||||
|
||||
facmax = static_cast<int> (sqrt((double) n));
|
||||
|
||||
for (n1 = facmax; n1 > 0; n1--) {
|
||||
n2 = n/n1;
|
||||
if (n1*n2 == n) {
|
||||
*factor1 = n1;
|
||||
*factor2 = n2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
perform just the 1d FFTs needed by a 3d FFT, no data movement
|
||||
used for timing purposes
|
||||
|
||||
Arguments:
|
||||
in starting address of input data on this proc, all set to 0.0
|
||||
nsize size of in
|
||||
flag 1 for forward FFT, -1 for inverse FFT
|
||||
plan plan returned by previous call to fft_3d_create_plan
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void fft_1d_only(FFT_DATA *data, int nsize, int flag, struct fft_plan_3d *plan)
|
||||
{
|
||||
int i,total,length,offset,num;
|
||||
double norm;
|
||||
|
||||
// system specific constants
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
int isys = 0;
|
||||
FFT_PREC scalef = 1.0;
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
char c = 'C';
|
||||
char f = 'F';
|
||||
char b = 'B';
|
||||
int one = 1;
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
int isys = 0;
|
||||
double scalef = 1.0;
|
||||
#endif
|
||||
|
||||
// total = size of data needed in each dim
|
||||
// length = length of 1d FFT in each dim
|
||||
// total/length = # of 1d FFTs in each dim
|
||||
// if total > nsize, limit # of 1d FFTs to available size of data
|
||||
|
||||
int total1 = plan->total1;
|
||||
int length1 = plan->length1;
|
||||
int total2 = plan->total2;
|
||||
int length2 = plan->length2;
|
||||
int total3 = plan->total3;
|
||||
int length3 = plan->length3;
|
||||
|
||||
if (total1 > nsize) total1 = (nsize/length1) * length1;
|
||||
if (total2 > nsize) total2 = (nsize/length2) * length2;
|
||||
if (total3 > nsize) total3 = (nsize/length3) * length3;
|
||||
|
||||
// perform 1d FFTs in each of 3 dimensions
|
||||
// data is just an array of 0.0
|
||||
|
||||
#ifdef FFT_SGI
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(flag,length1,&data[offset],1,plan->coeff1);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(flag,length2,&data[offset],1,plan->coeff2);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(flag,length3,&data[offset],1,plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(flag,length1,scalef,&data[offset],&data[offset],plan->coeff1,
|
||||
plan->work1,&isys);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(flag,length2,scalef,&data[offset],&data[offset],plan->coeff2,
|
||||
plan->work2,&isys);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(flag,length3,scalef,&data[offset],&data[offset],plan->coeff3,
|
||||
plan->work3,&isys);
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(&data[offset],&length1,&flag,plan->coeff1);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(&data[offset],&length2,&flag,plan->coeff2);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(&data[offset],&length3,&flag,plan->coeff3);
|
||||
#endif
|
||||
#ifdef FFT_DEC
|
||||
if (flag == -1) {
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length1,&one);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length2,&one);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length3,&one);
|
||||
} else {
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length1,&one);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length2,&one);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length3,&one);
|
||||
}
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
for (offset = 0; offset < total1; offset += length1)
|
||||
FFT_1D(&flag,&length1,&scalef,&data[offset],&data[offset],plan->coeff1,
|
||||
plan->work1,&isys);
|
||||
for (offset = 0; offset < total2; offset += length2)
|
||||
FFT_1D(&flag,&length2,&scalef,&data[offset],&data[offset],plan->coeff2,
|
||||
plan->work2,&isys);
|
||||
for (offset = 0; offset < total3; offset += length3)
|
||||
FFT_1D(&flag,&length3,&scalef,&data[offset],&data[offset],plan->coeff3,
|
||||
plan->work3,&isys);
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
if (flag == -1) {
|
||||
fftw(plan->plan_fast_forward,total1/length1,data,1,0,NULL,0,0);
|
||||
fftw(plan->plan_mid_forward,total2/length2,data,1,0,NULL,0,0);
|
||||
fftw(plan->plan_slow_forward,total3/length3,data,1,0,NULL,0,0);
|
||||
} else {
|
||||
fftw(plan->plan_fast_backward,total1/length1,data,1,0,NULL,0,0);
|
||||
fftw(plan->plan_mid_backward,total2/length2,data,1,0,NULL,0,0);
|
||||
fftw(plan->plan_slow_backward,total3/length3,data,1,0,NULL,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// scaling if required
|
||||
// limit num to size of data
|
||||
|
||||
#ifndef FFT_T3E
|
||||
if (flag == 1 && plan->scaled) {
|
||||
norm = plan->norm;
|
||||
num = MIN(plan->normnum,nsize);
|
||||
for (i = 0; i < num; i++) {
|
||||
data[i].re *= norm;
|
||||
data[i].im *= norm;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_T3E
|
||||
if (flag == 1 && plan->scaled) {
|
||||
norm = plan->norm;
|
||||
num = MIN(plan->normnum,nsize);
|
||||
for (i = 0; i < num; i++) data[i] *= (norm,norm);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
242
src/fft3d.h
242
src/fft3d.h
@ -1,242 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
// User-settable FFT precision
|
||||
|
||||
// FFT_PRECISION = 1 is single-precision complex (4-byte real, 4-byte imag)
|
||||
// FFT_PRECISION = 2 is double-precision complex (8-byte real, 8-byte imag)
|
||||
|
||||
#define FFT_PRECISION 2
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Data types for single-precision complex
|
||||
|
||||
#if FFT_PRECISION == 1
|
||||
|
||||
#ifdef FFT_SGI
|
||||
#include "fft.h"
|
||||
typedef complex FFT_DATA;
|
||||
#define FFT_1D cfft1d
|
||||
#define FFT_1D_INIT cfft1di
|
||||
extern "C" {
|
||||
int cfft1d(int, int, FFT_DATA *, int, FFT_DATA *);
|
||||
FFT_DATA *cfft1di(int, FFT_DATA *);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
#include <scsl_fft.h>
|
||||
typedef scsl_complex FFT_DATA;
|
||||
typedef float FFT_PREC;
|
||||
#define FFT_1D ccfft
|
||||
#define FFT_1D_INIT ccfft
|
||||
extern "C" {
|
||||
int ccfft(int, int, FFT_PREC, FFT_DATA *, FFT_DATA *,
|
||||
FFT_PREC *, FFT_PREC *, int *);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FFT_INTEL
|
||||
typedef struct {
|
||||
float re;
|
||||
float im;
|
||||
} FFT_DATA;
|
||||
#define FFT_1D cfft1d_
|
||||
#define FFT_1D_INIT cfft1d_
|
||||
extern "C" {
|
||||
void cfft1d_(FFT_DATA *, int *, int *, FFT_DATA *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_DEC
|
||||
typedef struct {
|
||||
float re;
|
||||
float im;
|
||||
} FFT_DATA;
|
||||
#define FFT_1D cfft_
|
||||
extern "C" {
|
||||
void cfft_(char *, char *, char *, FFT_DATA *, FFT_DATA *, int *, int *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_T3E
|
||||
#include <complex.h>
|
||||
typedef complex single FFT_DATA;
|
||||
#define FFT_1D GGFFT
|
||||
#define FFT_1D_INIT GGFFT
|
||||
extern "C" {
|
||||
void GGFFT(int *, int *, double *, FFT_DATA *, FFT_DATA *,
|
||||
double *, double *, int *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_FFTW
|
||||
#include "fftw.h"
|
||||
typedef FFTW_COMPLEX FFT_DATA;
|
||||
#endif
|
||||
|
||||
#ifdef FFT_NONE
|
||||
typedef struct {
|
||||
float re;
|
||||
float im;
|
||||
} FFT_DATA;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Data types for double-precision complex
|
||||
|
||||
#if FFT_PRECISION == 2
|
||||
|
||||
#ifdef FFT_SGI
|
||||
#include "fft.h"
|
||||
typedef zomplex FFT_DATA;
|
||||
#define FFT_1D zfft1d
|
||||
#define FFT_1D_INIT zfft1di
|
||||
extern "C" {
|
||||
int zfft1d(int, int, FFT_DATA *, int, FFT_DATA *);
|
||||
FFT_DATA *zfft1di(int, FFT_DATA *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_SCSL
|
||||
#include <scsl_fft.h>
|
||||
typedef scsl_zomplex FFT_DATA;
|
||||
typedef double FFT_PREC;
|
||||
#define FFT_1D zzfft
|
||||
#define FFT_1D_INIT zzfft
|
||||
extern "C" {
|
||||
int zzfft(int, int, FFT_PREC, FFT_DATA *, FFT_DATA *,
|
||||
FFT_PREC *, FFT_PREC *, int *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_INTEL
|
||||
typedef struct {
|
||||
double re;
|
||||
double im;
|
||||
} FFT_DATA;
|
||||
#define FFT_1D zfft1d_
|
||||
#define FFT_1D_INIT zfft1d_
|
||||
extern "C" {
|
||||
void zfft1d_(FFT_DATA *, int *, int *, FFT_DATA *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_DEC
|
||||
typedef struct {
|
||||
double re;
|
||||
double im;
|
||||
} FFT_DATA;
|
||||
#define FFT_1D zfft_
|
||||
extern "C" {
|
||||
void zfft_(char *, char *, char *, FFT_DATA *, FFT_DATA *, int *, int *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_T3E
|
||||
#include <complex.h>
|
||||
typedef complex double FFT_DATA;
|
||||
#define FFT_1D CCFFT
|
||||
#define FFT_1D_INIT CCFFT
|
||||
extern "C" {
|
||||
void CCFFT(int *, int *, double *, FFT_DATA *, FFT_DATA *,
|
||||
double *, double *, int *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FFT_FFTW
|
||||
#include "fftw.h"
|
||||
typedef FFTW_COMPLEX FFT_DATA;
|
||||
#endif
|
||||
|
||||
#ifdef FFT_NONE
|
||||
typedef struct {
|
||||
double re;
|
||||
double im;
|
||||
} FFT_DATA;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// details of how to do a 3d FFT
|
||||
|
||||
struct fft_plan_3d {
|
||||
struct remap_plan_3d *pre_plan; // remap from input -> 1st FFTs
|
||||
struct remap_plan_3d *mid1_plan; // remap from 1st -> 2nd FFTs
|
||||
struct remap_plan_3d *mid2_plan; // remap from 2nd -> 3rd FFTs
|
||||
struct remap_plan_3d *post_plan; // remap from 3rd FFTs -> output
|
||||
FFT_DATA *copy; // memory for remap results (if needed)
|
||||
FFT_DATA *scratch; // scratch space for remaps
|
||||
int total1,total2,total3; // # of 1st,2nd,3rd FFTs (times length)
|
||||
int length1,length2,length3; // length of 1st,2nd,3rd FFTs
|
||||
int pre_target; // where to put remap results
|
||||
int mid1_target,mid2_target;
|
||||
int scaled; // whether to scale FFT results
|
||||
int normnum; // # of values to rescale
|
||||
double norm; // normalization factor for rescaling
|
||||
|
||||
// system specific 1d FFT info
|
||||
#ifdef FFT_SGI
|
||||
FFT_DATA *coeff1;
|
||||
FFT_DATA *coeff2;
|
||||
FFT_DATA *coeff3;
|
||||
#endif
|
||||
#ifdef FFT_SCSL
|
||||
FFT_PREC *coeff1;
|
||||
FFT_PREC *coeff2;
|
||||
FFT_PREC *coeff3;
|
||||
FFT_PREC *work1;
|
||||
FFT_PREC *work2;
|
||||
FFT_PREC *work3;
|
||||
#endif
|
||||
#ifdef FFT_INTEL
|
||||
FFT_DATA *coeff1;
|
||||
FFT_DATA *coeff2;
|
||||
FFT_DATA *coeff3;
|
||||
#endif
|
||||
#ifdef FFT_T3E
|
||||
double *coeff1;
|
||||
double *coeff2;
|
||||
double *coeff3;
|
||||
double *work1;
|
||||
double *work2;
|
||||
double *work3;
|
||||
#endif
|
||||
#ifdef FFT_FFTW
|
||||
fftw_plan plan_fast_forward;
|
||||
fftw_plan plan_fast_backward;
|
||||
fftw_plan plan_mid_forward;
|
||||
fftw_plan plan_mid_backward;
|
||||
fftw_plan plan_slow_forward;
|
||||
fftw_plan plan_slow_backward;
|
||||
#endif
|
||||
};
|
||||
|
||||
// function prototypes
|
||||
|
||||
void fft_3d(FFT_DATA *, FFT_DATA *, int, struct fft_plan_3d *);
|
||||
struct fft_plan_3d *fft_3d_create_plan(MPI_Comm, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int *);
|
||||
void fft_3d_destroy_plan(struct fft_plan_3d *);
|
||||
void factor(int, int *, int *);
|
||||
void bifactor(int, int *, int *);
|
||||
void fft_1d_only(FFT_DATA *, int, int, struct fft_plan_3d *);
|
||||
@ -1,53 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "fft3d_wrap.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FFT3d::FFT3d(MPI_Comm comm, int nfast, int nmid, int nslow,
|
||||
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
|
||||
int in_klo, int in_khi,
|
||||
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
|
||||
int out_klo, int out_khi,
|
||||
int scaled, int permute, int *nbuf)
|
||||
{
|
||||
plan = fft_3d_create_plan(comm,nfast,nmid,nslow,
|
||||
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
|
||||
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
|
||||
scaled,permute,nbuf);
|
||||
if (plan == NULL) error->one("Could not create 3d FFT plan");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FFT3d::~FFT3d()
|
||||
{
|
||||
fft_3d_destroy_plan(plan);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FFT3d::compute(double *in, double *out, int flag)
|
||||
{
|
||||
fft_3d((FFT_DATA *) in,(FFT_DATA *) out,flag,plan);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FFT3d::timing1d(double *in, int nsize, int flag)
|
||||
{
|
||||
fft_1d_only((FFT_DATA *) in,nsize,flag,plan);
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFT3D_WRAP_H
|
||||
#define FFT3D_WRAP_H
|
||||
|
||||
#include "lammps.h"
|
||||
#include "fft3d.h"
|
||||
|
||||
class FFT3d : public LAMMPS {
|
||||
public:
|
||||
FFT3d(MPI_Comm,int,int,int,int,int,int,int,int,int,
|
||||
int,int,int,int,int,int,int,int,int *);
|
||||
~FFT3d();
|
||||
void compute(double *, double *, int);
|
||||
void timing1d(double *, int, int);
|
||||
|
||||
private:
|
||||
struct fft_plan_3d *plan;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,36 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "improper.h"
|
||||
#include "atom.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Improper::Improper()
|
||||
{
|
||||
allocated = 0;
|
||||
PI = 4.0*atan(1.0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if all coeffs are set
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Improper::init()
|
||||
{
|
||||
if (!allocated) error->all("Improper coeffs are not set");
|
||||
for (int i = 1; i <= atom->nimpropertypes; i++)
|
||||
if (setflag[i] == 0) error->all("All improper coeffs are not set");
|
||||
}
|
||||
@ -1,352 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "improper_cvff.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
ImproperCvff::~ImproperCvff()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(sign);
|
||||
memory->sfree(multiplicity);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvff::compute(int eflag, int vflag)
|
||||
{
|
||||
int m,n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y;
|
||||
double vb2z,vb2xm,vb2ym,vb2zm,vb3x,vb3y,vb3z,sb1;
|
||||
double sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,p,pd,rc2,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx1,sx2,sx12,sy1,sy2,sy12;
|
||||
double sz1,sz2,sz12,s2;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **improperlist = neighbor->improperlist;
|
||||
int nimproperlist = neighbor->nimproperlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nimproperlist; n++) {
|
||||
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
domain->minimum_image(&vb1x,&vb1y,&vb1z);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&vb2x,&vb2y,&vb2z);
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
domain->minimum_image(&vb2xm,&vb2ym,&vb2zm);
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&vb3x,&vb3y,&vb3z);
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sc1 = sqrt(1.0 - c1mag*c1mag);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sc2 = sqrt(1.0 - c2mag*c2mag);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me;
|
||||
MPI_Comm_rank(world,&me);
|
||||
if (screen) {
|
||||
fprintf(screen,"Improper problem: %d %d %d %d %d %d\n",
|
||||
me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = 1 + cos(n*phi) for d = 1
|
||||
// p = 1 - cos(n*phi) for d = -1
|
||||
// pd = dp/dc / 2
|
||||
|
||||
m = multiplicity[type];
|
||||
|
||||
if (m == 2) {
|
||||
p = 2.0*c*c;
|
||||
pd = 2.0*c;
|
||||
} else if (m == 3) {
|
||||
rc2 = c*c;
|
||||
p = (4.0*rc2-3.0)*c + 1.0;
|
||||
pd = 6.0*rc2 - 1.5;
|
||||
} else if (m == 4) {
|
||||
rc2 = c*c;
|
||||
p = 8.0*(rc2-1)*rc2 + 2.0;
|
||||
pd = (16.0*rc2-8.0)*c;
|
||||
} else if (m == 6) {
|
||||
rc2 = c*c;
|
||||
p = ((32.0*rc2-48.0)*rc2 + 18.0)*rc2;
|
||||
pd = (96.0*(rc2-1.0)*rc2 + 18.0)*c;
|
||||
} else if (m == 1) {
|
||||
p = c + 1.0;
|
||||
pd = 0.5;
|
||||
} else if (m == 5) {
|
||||
rc2 = c*c;
|
||||
p = ((16.0*rc2-20.0)*rc2 + 5.0)*c + 1.0;
|
||||
pd = (40.0*rc2-30.0)*rc2 + 2.5;
|
||||
} else if (m == 0) {
|
||||
p = 2.0;
|
||||
pd = 0.0;
|
||||
}
|
||||
|
||||
if (sign[type] == -1) {
|
||||
p = 2.0 - p;
|
||||
pd = -pd;
|
||||
}
|
||||
|
||||
if (eflag) energy += rfactor * k[type] * p;
|
||||
|
||||
a = 2.0 * k[type] * pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = (-c*sb1*s1);
|
||||
a22 = sb2*(2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = (-c*sb3*s2);
|
||||
a12 = r12c1*(c1mag*c*s1 + c2mag*s12);
|
||||
a13 = rb1*rb3*s12;
|
||||
a23 = r12c2*(-c2mag*c*s2 - c1mag*s12);
|
||||
|
||||
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] -= rfactor * (vb1x*sx1 + vb2x*sx2 + vb3x*sx12);
|
||||
virial[1] -= rfactor * (vb1y*sy1 + vb2y*sy2 + vb3y*sy12);
|
||||
virial[2] -= rfactor * (vb1z*sz1 + vb2z*sz2 + vb3z*sz12);
|
||||
virial[3] -= rfactor * (vb1x*sy1 + vb2x*sy2 + vb3x*sy12);
|
||||
virial[4] -= rfactor * (vb1x*sz1 + vb2x*sz2 + vb3x*sz12);
|
||||
virial[5] -= rfactor * (vb1y*sz1 + vb2y*sz2 + vb3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvff::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nimpropertypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"improper:k");
|
||||
sign = (int *) memory->smalloc((n+1)*sizeof(int),"improper:sign");
|
||||
multiplicity = (int *)
|
||||
memory->smalloc((n+1)*sizeof(int),"improper:multiplicity");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"improper:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvff::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this improper style");
|
||||
if (narg != 4) error->all("Incorrect args for improper coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
int sign_one = atoi(arg[2]);
|
||||
int multiplicity_one = atoi(arg[3]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
sign[i] = sign_one;
|
||||
multiplicity[i] = multiplicity_one;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for improper coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvff::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
fwrite(&sign[1],sizeof(int),atom->nimpropertypes,fp);
|
||||
fwrite(&multiplicity[1],sizeof(int),atom->nimpropertypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvff::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
fread(&sign[1],sizeof(int),atom->nimpropertypes,fp);
|
||||
fread(&multiplicity[1],sizeof(int),atom->nimpropertypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sign[1],atom->nimpropertypes,MPI_INT,0,world);
|
||||
MPI_Bcast(&multiplicity[1],atom->nimpropertypes,MPI_INT,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef IMPROPER_CVFF_H
|
||||
#define IMPROPER_CVFF_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "improper.h"
|
||||
|
||||
class ImproperCvff : public Improper {
|
||||
public:
|
||||
ImproperCvff() {}
|
||||
~ImproperCvff();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *k;
|
||||
int *sign,*multiplicity;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,286 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "stdlib.h"
|
||||
#include "improper_harmonic.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
ImproperHarmonic::~ImproperHarmonic()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(k);
|
||||
memory->sfree(chi);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonic::compute(int eflag, int vflag)
|
||||
{
|
||||
int n,i1,i2,i3,i4,type,factor;
|
||||
double rfactor;
|
||||
double v1x,v1y,v1z,v2x,v2y,v2z,v3x;
|
||||
double v3y,v3z,ss1,ss2,ss3,r1,r2,r3,c0,c1,c2,s1,s2;
|
||||
double s12,c,s,domega,a,a11,a22,a33,a12,a13,a23,sx1;
|
||||
double sx2,sx12,sy1,sy2,sy12,sz1,sz2,sz12;
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int **improperlist = neighbor->improperlist;
|
||||
int nimproperlist = neighbor->nimproperlist;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_bond = force->newton_bond;
|
||||
|
||||
for (n = 0; n < nimproperlist; n++) {
|
||||
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
if (newton_bond) factor = 4;
|
||||
else {
|
||||
factor = 0;
|
||||
if (i1 < nlocal) factor++;
|
||||
if (i2 < nlocal) factor++;
|
||||
if (i3 < nlocal) factor++;
|
||||
if (i4 < nlocal) factor++;
|
||||
}
|
||||
rfactor = 0.25 * factor;
|
||||
|
||||
// geometry of 4-body
|
||||
|
||||
v1x = x[i2][0] - x[i1][0];
|
||||
v1y = x[i2][1] - x[i1][1];
|
||||
v1z = x[i2][2] - x[i1][2];
|
||||
domain->minimum_image(&v1x,&v1y,&v1z);
|
||||
|
||||
v2x = x[i3][0] - x[i2][0];
|
||||
v2y = x[i3][1] - x[i2][1];
|
||||
v2z = x[i3][2] - x[i2][2];
|
||||
domain->minimum_image(&v2x,&v2y,&v2z);
|
||||
|
||||
v3x = x[i4][0] - x[i3][0];
|
||||
v3y = x[i4][1] - x[i3][1];
|
||||
v3z = x[i4][2] - x[i3][2];
|
||||
domain->minimum_image(&v3x,&v3y,&v3z);
|
||||
|
||||
ss1 = 1.0 / (v1x*v1x + v1y*v1y + v1z*v1z);
|
||||
ss2 = 1.0 / (v2x*v2x + v2y*v2y + v2z*v2z);
|
||||
ss3 = 1.0 / (v3x*v3x + v3y*v3y + v3z*v3z);
|
||||
|
||||
r1 = sqrt(ss1);
|
||||
r2 = sqrt(ss2);
|
||||
r3 = sqrt(ss3);
|
||||
|
||||
// sin and cos of angle
|
||||
|
||||
c0 = -(v1x * v3x + v1y * v3y + v1z * v3z) * r1 * r3;
|
||||
c1 = -(v1x * v2x + v1y * v2y + v1z * v2z) * r1 * r2;
|
||||
c2 = -(v3x * v2x + v3y * v2y + v3z * v2z) * r3 * r2;
|
||||
|
||||
s1 = 1.0 - c1*c1;
|
||||
if (s1 < SMALL) s1 = SMALL;
|
||||
s1 = 1.0 / s1;
|
||||
|
||||
s2 = 1.0 - c2*c2;
|
||||
if (s2 < SMALL) s2 = SMALL;
|
||||
s2 = 1.0 / s2;
|
||||
|
||||
s12 = sqrt(s1*s2);
|
||||
c = (c1*c2 + c0) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me;
|
||||
MPI_Comm_rank(world,&me);
|
||||
if (screen) {
|
||||
fprintf(screen,"Improper problem: %d %d %d %d %d %d\n",
|
||||
me,update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
|
||||
// force & energy
|
||||
|
||||
domega = acos(c) - chi[type];
|
||||
a = k[type] * domega;
|
||||
|
||||
if (eflag) energy += rfactor * a * domega;
|
||||
|
||||
a = -a * 2.0/s;
|
||||
c = c * a;
|
||||
|
||||
s12 = s12 * a;
|
||||
a11 = (-c * ss1 * s1);
|
||||
a22 = ss2 * (2.0 * c0 * s12 - c * (s1 + s2));
|
||||
a33 = (-c * ss3 * s2);
|
||||
a12 = r1 * r2 * (c1 * c * s1 + c2 * s12);
|
||||
a13 = r1 * r3 * s12;
|
||||
a23 = r2 * r3 * (-c2 * c * s2 - c1 * s12);
|
||||
|
||||
sx1 = a12*v2x + a13*v3x - a11*v1x;
|
||||
sx2 = a22*v2x + a23*v3x - a12*v1x;
|
||||
sx12 = a23*v2x + a33*v3x - a13*v1x;
|
||||
sy1 = a12*v2y + a13*v3y - a11*v1y;
|
||||
sy2 = a22*v2y + a23*v3y - a12*v1y;
|
||||
sy12 = a23*v2y + a33*v3y - a13*v1y;
|
||||
sz1 = a12*v2z + a13*v3z - a11*v1z;
|
||||
sz2 = a22*v2z + a23*v3z - a12*v1z;
|
||||
sz12 = a23*v2z + a33*v3z - a13*v1z;
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (newton_bond || i1 < nlocal) {
|
||||
f[i1][0] -= sx1;
|
||||
f[i1][1] -= sy1;
|
||||
f[i1][2] -= sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i2 < nlocal) {
|
||||
f[i2][0] += sx2 + sx1;
|
||||
f[i2][1] += sy2 + sy1;
|
||||
f[i2][2] += sz2 + sz1;
|
||||
}
|
||||
|
||||
if (newton_bond || i3 < nlocal) {
|
||||
f[i3][0] += sx12 - sx2;
|
||||
f[i3][1] += sy12 - sy2;
|
||||
f[i3][2] += sz12 - sz2;
|
||||
}
|
||||
|
||||
if (newton_bond || i4 < nlocal) {
|
||||
f[i4][0] -= sx12;
|
||||
f[i4][1] -= sy12;
|
||||
f[i4][2] -= sz12;
|
||||
}
|
||||
|
||||
// virial contribution
|
||||
|
||||
if (vflag) {
|
||||
virial[0] += rfactor * (v1x*sx1 - v2x*sx2 - v3x*sx12);
|
||||
virial[1] += rfactor * (v1y*sy1 - v2y*sy2 - v3y*sy12);
|
||||
virial[2] += rfactor * (v1z*sz1 - v2z*sz2 - v3z*sz12);
|
||||
virial[3] += rfactor * (v1x*sy1 - v2x*sy2 - v3x*sy12);
|
||||
virial[4] += rfactor * (v1x*sz1 - v2x*sz2 - v3x*sz12);
|
||||
virial[5] += rfactor * (v1y*sz1 - v2y*sz2 - v3y*sz12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonic::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nimpropertypes;
|
||||
|
||||
k = (double *) memory->smalloc((n+1)*sizeof(double),"improper:k");
|
||||
chi = (double *) memory->smalloc((n+1)*sizeof(double),"improper:chi");
|
||||
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"improper:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonic::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (which != 0) error->all("Invalid coeffs for this improper style");
|
||||
if (narg != 3) error->all("Incorrect args for improper coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
|
||||
|
||||
double k_one = atof(arg[1]);
|
||||
double chi_one = atof(arg[2]);
|
||||
|
||||
// convert chi from degrees to radians
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
k[i] = k_one;
|
||||
chi[i] = chi_one/180.0 * PI;
|
||||
setflag[i] = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for improper coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes out coeffs to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonic::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
fwrite(&chi[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads coeffs from restart file, bcasts them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonic::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
if (comm->me == 0) {
|
||||
fread(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
fread(&chi[1],sizeof(double),atom->nimpropertypes,fp);
|
||||
}
|
||||
MPI_Bcast(&k[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&chi[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||
|
||||
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef IMPROPER_HARMONIC_H
|
||||
#define IMPROPER_HARMONIC_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "improper.h"
|
||||
|
||||
class ImproperHarmonic : public Improper {
|
||||
public:
|
||||
ImproperHarmonic() {}
|
||||
~ImproperHarmonic();
|
||||
void compute(int, int);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
|
||||
private:
|
||||
double *k,*chi;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,246 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "improper_hybrid.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define EXTRA 1000
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set all global defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
ImproperHybrid::ImproperHybrid()
|
||||
{
|
||||
nstyles = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
ImproperHybrid::~ImproperHybrid()
|
||||
{
|
||||
if (nstyles) {
|
||||
for (int i = 0; i < nstyles; i++) delete styles[i];
|
||||
delete [] styles;
|
||||
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
|
||||
delete [] keywords;
|
||||
}
|
||||
|
||||
if (allocated) {
|
||||
memory->sfree(setflag);
|
||||
memory->sfree(map);
|
||||
delete [] nimproperlist;
|
||||
delete [] maximproper;
|
||||
for (int i = 0; i < nstyles; i++)
|
||||
memory->destroy_2d_int_array(improperlist[i]);
|
||||
delete [] improperlist;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,m,n;
|
||||
|
||||
// save ptrs to original improperlist
|
||||
|
||||
int nimproperlist_orig = neighbor->nimproperlist;
|
||||
int **improperlist_orig = neighbor->improperlist;
|
||||
|
||||
// if this is re-neighbor step, create sub-style improperlists
|
||||
// nimproperlist[] = length of each sub-style list
|
||||
// realloc sub-style improperlist if necessary
|
||||
// load sub-style improperlist with 5 values from original improperlist
|
||||
|
||||
if (neighbor->ago == 0) {
|
||||
for (m = 0; m < nstyles; m++) nimproperlist[m] = 0;
|
||||
for (i = 0; i < nimproperlist_orig; i++)
|
||||
nimproperlist[map[improperlist_orig[i][4]]]++;
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (nimproperlist[m] > maximproper[m]) {
|
||||
memory->destroy_2d_int_array(improperlist[m]);
|
||||
maximproper[m] = nimproperlist[m] + EXTRA;
|
||||
improperlist[m] = (int **)
|
||||
memory->create_2d_int_array(maximproper[m],5,
|
||||
"improper_hybrid:improperlist");
|
||||
}
|
||||
nimproperlist[m] = 0;
|
||||
}
|
||||
for (i = 0; i < nimproperlist_orig; i++) {
|
||||
m = map[improperlist_orig[i][4]];
|
||||
n = nimproperlist[m];
|
||||
improperlist[m][n][0] = improperlist_orig[i][0];
|
||||
improperlist[m][n][1] = improperlist_orig[i][1];
|
||||
improperlist[m][n][2] = improperlist_orig[i][2];
|
||||
improperlist[m][n][3] = improperlist_orig[i][3];
|
||||
improperlist[m][n][4] = improperlist_orig[i][4];
|
||||
nimproperlist[m]++;
|
||||
}
|
||||
}
|
||||
|
||||
// call each sub-style's compute function
|
||||
// must set neighbor->improperlist to sub-style improperlist before call
|
||||
// accumulate sub-style energy,virial in hybrid's energy,virial
|
||||
|
||||
energy = 0.0;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
|
||||
|
||||
for (m = 0; m < nstyles; m++) {
|
||||
if (styles[m] == NULL) continue;
|
||||
neighbor->nimproperlist = nimproperlist[m];
|
||||
neighbor->improperlist = improperlist[m];
|
||||
styles[m]->compute(eflag,vflag);
|
||||
if (eflag) energy += styles[m]->energy;
|
||||
if (vflag) for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
|
||||
}
|
||||
|
||||
// restore ptrs to original improperlist
|
||||
|
||||
neighbor->nimproperlist = nimproperlist_orig;
|
||||
neighbor->improperlist = improperlist_orig;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->nimpropertypes;
|
||||
|
||||
map = (int *) memory->smalloc((n+1)*sizeof(int),"improper:map");
|
||||
setflag = (int *) memory->smalloc((n+1)*sizeof(int),"improper:setflag");
|
||||
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||
|
||||
nimproperlist = new int[nstyles];
|
||||
maximproper = new int[nstyles];
|
||||
improperlist = new int**[nstyles];
|
||||
for (int m = 0; m < nstyles; m++) maximproper[m] = 0;
|
||||
for (int m = 0; m < nstyles; m++) improperlist[m] = NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create one improper style for each arg in list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::settings(int narg, char **arg)
|
||||
{
|
||||
nstyles = narg;
|
||||
styles = new Improper*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
for (int i = 0; i < m; i++)
|
||||
if (strcmp(arg[m],arg[i]) == 0)
|
||||
error->all("Improper style hybrid cannot use same improper style twice");
|
||||
if (strcmp(arg[m],"hybrid") == 0)
|
||||
error->all("Improper style hybrid cannot have hybrid as an argument");
|
||||
styles[m] = force->new_improper(arg[m]);
|
||||
keywords[m] = new char[strlen(arg[m])+1];
|
||||
strcpy(keywords[m],arg[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one type
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::coeff(int which, int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi;
|
||||
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
|
||||
|
||||
// 2nd arg = improper style name (harmonic, etc)
|
||||
|
||||
int m;
|
||||
for (m = 0; m < nstyles; m++)
|
||||
if (strcmp(arg[1],keywords[m]) == 0) break;
|
||||
if (m == nstyles) error->all("Improper coeff for hybrid has invalid style");
|
||||
|
||||
// set low-level coefficients for each impropertype
|
||||
// replace 2nd arg with i, call coeff() with no 1st arg
|
||||
// if sub-style is NULL for "none", still set setflag
|
||||
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
sprintf(arg[1],"%d",i);
|
||||
map[i] = m;
|
||||
if (styles[m]) styles[m]->coeff(which,narg-1,&arg[1]);
|
||||
setflag[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::write_restart(FILE *fp)
|
||||
{
|
||||
fwrite(&nstyles,sizeof(int),1,fp);
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
n = strlen(keywords[m]) + 1;
|
||||
fwrite(&n,sizeof(int),1,fp);
|
||||
fwrite(keywords[m],sizeof(char),n,fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHybrid::read_restart(FILE *fp)
|
||||
{
|
||||
allocate();
|
||||
|
||||
int me = comm->me;
|
||||
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
|
||||
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
|
||||
styles = new Improper*[nstyles];
|
||||
keywords = new char*[nstyles];
|
||||
|
||||
int n;
|
||||
for (int m = 0; m < nstyles; m++) {
|
||||
if (me == 0) fread(&n,sizeof(int),1,fp);
|
||||
MPI_Bcast(&n,1,MPI_INT,0,world);
|
||||
keywords[m] = new char[n];
|
||||
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
|
||||
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
|
||||
styles[m] = force->new_improper(keywords[m]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ImproperHybrid::memory_usage()
|
||||
{
|
||||
int bytes = 0;
|
||||
for (int m = 0; m < nstyles; m++) bytes += maximproper[m]*5 * sizeof(int);
|
||||
for (int m = 0; m < nstyles; m++)
|
||||
if (styles[m]) bytes += styles[m]->memory_usage();
|
||||
return bytes;
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef IMPROPER_HYBRID_H
|
||||
#define IMPROPER_HYBRID_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "improper.h"
|
||||
|
||||
class ImproperHybrid : public Improper {
|
||||
public:
|
||||
ImproperHybrid();
|
||||
~ImproperHybrid();
|
||||
void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, int, char **);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
int memory_usage();
|
||||
|
||||
private:
|
||||
int nstyles; // # of different improper styles
|
||||
Improper **styles; // class list for each Improper style
|
||||
char **keywords; // keyword for each improper style
|
||||
int *map; // which style each improper type points to
|
||||
|
||||
int *nimproperlist; // # of impropers in sub-style improperlists
|
||||
int *maximproper; // max # of impropers sub-style lists can store
|
||||
int ***improperlist; // improperlist for each sub-style
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -156,6 +156,14 @@ void Input::file()
|
||||
|
||||
MPI_Bcast(line,n,MPI_CHAR,0,world);
|
||||
|
||||
// if n = MAXLINE, line is too long
|
||||
|
||||
if (n == MAXLINE) {
|
||||
char str[MAXLINE+32];
|
||||
sprintf(str,"Input line too long: %s",line);
|
||||
error->all(str);
|
||||
}
|
||||
|
||||
// echo the command unless scanning for label
|
||||
|
||||
if (me == 0 && label_active == 0) {
|
||||
|
||||
@ -1,446 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "pair_buck_coul_long.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "kspace.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define EWALD_F 1.12837917
|
||||
#define EWALD_P 0.3275911
|
||||
#define A1 0.254829592
|
||||
#define A2 -0.284496736
|
||||
#define A3 1.421413741
|
||||
#define A4 -1.453152027
|
||||
#define A5 1.061405429
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
PairBuckCoulLong::~PairBuckCoulLong()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->destroy_2d_int_array(setflag);
|
||||
memory->destroy_2d_double_array(cutsq);
|
||||
|
||||
memory->destroy_2d_double_array(cut_lj);
|
||||
memory->destroy_2d_double_array(cut_ljsq);
|
||||
memory->destroy_2d_double_array(a);
|
||||
memory->destroy_2d_double_array(rho);
|
||||
memory->destroy_2d_double_array(c);
|
||||
memory->destroy_2d_double_array(rhoinv);
|
||||
memory->destroy_2d_double_array(buck1);
|
||||
memory->destroy_2d_double_array(buck2);
|
||||
memory->destroy_2d_double_array(offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,numneigh,itype,jtype;
|
||||
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
|
||||
double rsq,r2inv,r6inv,forcecoul,forcebuck,fforce,factor_coul,factor_lj;
|
||||
double grij,expm2,prefactor,t,erfc;
|
||||
double factor,phicoul,phibuck,r,rexp;
|
||||
int *neighs;
|
||||
double **f;
|
||||
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) f = update->f_pair;
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
double *q = atom->q;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
double *special_coul = force->special_coul;
|
||||
double *special_lj = force->special_lj;
|
||||
int newton_pair = force->newton_pair;
|
||||
double qqrd2e = force->qqrd2e;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
qtmp = q[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
if (j < nall) factor_coul = factor_lj = 1.0;
|
||||
else {
|
||||
factor_coul = special_coul[j/nall];
|
||||
factor_lj = special_lj[j/nall];
|
||||
j %= nall;
|
||||
}
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
jtype = type[j];
|
||||
|
||||
if (rsq < cutsq[itype][jtype]) {
|
||||
r2inv = 1.0/rsq;
|
||||
|
||||
if (rsq < cut_coulsq) {
|
||||
r = sqrt(rsq);
|
||||
grij = g_ewald * r;
|
||||
expm2 = exp(-grij*grij);
|
||||
t = 1.0 / (1.0 + EWALD_P*grij);
|
||||
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
|
||||
prefactor = qqrd2e * qtmp*q[j]/r;
|
||||
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
|
||||
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
|
||||
} else forcecoul = 0.0;
|
||||
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
r = sqrt(rsq);
|
||||
rexp = exp(-r*rhoinv[itype][jtype]);
|
||||
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
|
||||
} else forcebuck = 0.0;
|
||||
|
||||
fforce = (forcecoul + factor_lj*forcebuck) * r2inv;
|
||||
|
||||
f[i][0] += delx*fforce;
|
||||
f[i][1] += dely*fforce;
|
||||
f[i][2] += delz*fforce;
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] -= delx*fforce;
|
||||
f[j][1] -= dely*fforce;
|
||||
f[j][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (newton_pair || j < nlocal) factor = 1.0;
|
||||
else factor = 0.5;
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = prefactor*erfc;
|
||||
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
|
||||
eng_coul += factor*phicoul;
|
||||
}
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
|
||||
offset[itype][jtype];
|
||||
eng_vdwl += factor*factor_lj*phibuck;
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag == 1) {
|
||||
if (newton_pair || j < nlocal) {
|
||||
virial[0] += delx*delx*fforce;
|
||||
virial[1] += dely*dely*fforce;
|
||||
virial[2] += delz*delz*fforce;
|
||||
virial[3] += delx*dely*fforce;
|
||||
virial[4] += delx*delz*fforce;
|
||||
virial[5] += dely*delz*fforce;
|
||||
} else {
|
||||
virial[0] += 0.5*delx*delx*fforce;
|
||||
virial[1] += 0.5*dely*dely*fforce;
|
||||
virial[2] += 0.5*delz*delz*fforce;
|
||||
virial[3] += 0.5*delx*dely*fforce;
|
||||
virial[4] += 0.5*delx*delz*fforce;
|
||||
virial[5] += 0.5*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) virial_compute();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
|
||||
|
||||
cut_lj = memory->create_2d_double_array(n+1,n+1,"pair:cut_lj");
|
||||
cut_ljsq = memory->create_2d_double_array(n+1,n+1,"pair:cut_ljsq");
|
||||
a = memory->create_2d_double_array(n+1,n+1,"pair:a");
|
||||
rho = memory->create_2d_double_array(n+1,n+1,"pair:rho");
|
||||
c = memory->create_2d_double_array(n+1,n+1,"pair:c");
|
||||
rhoinv = memory->create_2d_double_array(n+1,n+1,"pair:rhoinv");
|
||||
buck1 = memory->create_2d_double_array(n+1,n+1,"pair:buck1");
|
||||
buck2 = memory->create_2d_double_array(n+1,n+1,"pair:buck2");
|
||||
offset = memory->create_2d_double_array(n+1,n+1,"pair:offset");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
|
||||
|
||||
cut_lj_global = atof(arg[0]);
|
||||
if (narg == 1) cut_coul = cut_lj_global;
|
||||
else cut_coul = atof(arg[1]);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
|
||||
if (allocated) {
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i+1; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double a_one = atof(arg[2]);
|
||||
double rho_one = atof(arg[3]);
|
||||
double c_one = atof(arg[4]);
|
||||
|
||||
double cut_lj_one = cut_lj_global;
|
||||
if (narg == 6) cut_lj_one = atof(arg[5]);
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
a[i][j] = a_one;
|
||||
rho[i][j] = rho_one;
|
||||
c[i][j] = c_one;
|
||||
cut_lj[i][j] = cut_lj_one;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairBuckCoulLong::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
|
||||
|
||||
double cut = MAX(cut_lj[i][j],cut_coul);
|
||||
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
|
||||
|
||||
rhoinv[i][j] = 1.0/rho[i][j];
|
||||
buck1[i][j] = a[i][j]/rho[i][j];
|
||||
buck2[i][j] = 6.0*c[i][j];
|
||||
|
||||
if (offset_flag) {
|
||||
double rexp = exp(-cut_lj[i][j]/rho[i][j]);
|
||||
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut_lj[i][j],6.0);
|
||||
} else offset[i][j] = 0.0;
|
||||
|
||||
cut_ljsq[j][i] = cut_ljsq[i][j];
|
||||
a[j][i] = a[i][j];
|
||||
c[j][i] = c[i][j];
|
||||
rhoinv[j][i] = rhoinv[i][j];
|
||||
buck1[j][i] = buck1[i][j];
|
||||
buck2[j][i] = buck2[i][j];
|
||||
offset[j][i] = offset[i][j];
|
||||
|
||||
return cut;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::init_style()
|
||||
{
|
||||
// require an atom style with charge defined
|
||||
|
||||
if (atom->charge_allow == 0)
|
||||
error->all("Must use charged atom style with this pair style");
|
||||
|
||||
cut_coulsq = cut_coul * cut_coul;
|
||||
|
||||
// insure use of KSpace long-range solver, set g_ewald
|
||||
|
||||
if (force->kspace == NULL)
|
||||
error->all("Pair style is incompatible with KSpace style");
|
||||
else if (strcmp(force->kspace_style,"ewald") == 0)
|
||||
g_ewald = force->kspace->g_ewald;
|
||||
else if (strcmp(force->kspace_style,"pppm") == 0)
|
||||
g_ewald = force->kspace->g_ewald;
|
||||
else error->all("Pair style is incompatible with KSpace style");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::write_restart(FILE *fp)
|
||||
{
|
||||
write_restart_settings(fp);
|
||||
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
fwrite(&setflag[i][j],sizeof(int),1,fp);
|
||||
if (setflag[i][j]) {
|
||||
fwrite(&a[i][j],sizeof(double),1,fp);
|
||||
fwrite(&rho[i][j],sizeof(double),1,fp);
|
||||
fwrite(&c[i][j],sizeof(double),1,fp);
|
||||
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::read_restart(FILE *fp)
|
||||
{
|
||||
read_restart_settings(fp);
|
||||
|
||||
allocate();
|
||||
|
||||
int i,j;
|
||||
int me = comm->me;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
|
||||
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
|
||||
if (setflag[i][j]) {
|
||||
if (me == 0) {
|
||||
fread(&a[i][j],sizeof(double),1,fp);
|
||||
fread(&rho[i][j],sizeof(double),1,fp);
|
||||
fread(&c[i][j],sizeof(double),1,fp);
|
||||
fread(&cut_lj[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::write_restart_settings(FILE *fp)
|
||||
{
|
||||
fwrite(&cut_lj_global,sizeof(double),1,fp);
|
||||
fwrite(&cut_coul,sizeof(double),1,fp);
|
||||
fwrite(&offset_flag,sizeof(int),1,fp);
|
||||
fwrite(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::read_restart_settings(FILE *fp)
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
fread(&cut_lj_global,sizeof(double),1,fp);
|
||||
fread(&cut_coul,sizeof(double),1,fp);
|
||||
fread(&offset_flag,sizeof(int),1,fp);
|
||||
fread(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairBuckCoulLong::single(int i, int j, int itype, int jtype,
|
||||
double rsq, double factor_coul, double factor_lj,
|
||||
int eflag, One &one)
|
||||
{
|
||||
double r2inv,r6inv,r,rexp,grij,expm2,t,erfc,prefactor;
|
||||
double forcecoul,forcebuck,phicoul,phibuck;
|
||||
|
||||
r2inv = 1.0/rsq;
|
||||
if (rsq < cut_coulsq) {
|
||||
r = sqrt(rsq);
|
||||
grij = g_ewald * r;
|
||||
expm2 = exp(-grij*grij);
|
||||
t = 1.0 / (1.0 + EWALD_P*grij);
|
||||
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
|
||||
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
|
||||
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
|
||||
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
|
||||
} else forcecoul = 0.0;
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
r = sqrt(rsq);
|
||||
rexp = exp(-r*rhoinv[itype][jtype]);
|
||||
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
|
||||
} else forcebuck = 0.0;
|
||||
one.fforce = (forcecoul + factor_lj*forcebuck) * r2inv;
|
||||
|
||||
if (eflag) {
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = prefactor*erfc;
|
||||
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
|
||||
one.eng_coul = phicoul;
|
||||
} else one.eng_coul = 0.0;
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
|
||||
offset[itype][jtype];
|
||||
one.eng_vdwl = factor_lj*phibuck;
|
||||
} else one.eng_vdwl = 0.0;
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_BUCK_COUL_LONG_H
|
||||
#define PAIR_BUCK_COUL_LONG_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
class PairBuckCoulLong : public Pair {
|
||||
public:
|
||||
double cut_coul;
|
||||
|
||||
PairBuckCoulLong() {}
|
||||
~PairBuckCoulLong();
|
||||
void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, char **);
|
||||
double init_one(int, int);
|
||||
void init_style();
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void write_restart_settings(FILE *);
|
||||
void read_restart_settings(FILE *);
|
||||
void single(int, int, int, int, double, double, double, int, One &);
|
||||
|
||||
private:
|
||||
double cut_lj_global;
|
||||
double **cut_lj,**cut_ljsq;
|
||||
double cut_coulsq;
|
||||
double **a,**rho,**c;
|
||||
double **rhoinv,**buck1,**buck2,**offset;
|
||||
double g_ewald;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
927
src/pair_eam.cpp
927
src/pair_eam.cpp
@ -1,927 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Stephen Foiles (SNL), Murray Daw (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "pair_eam.h"
|
||||
#include "atom.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define MAXLINE 1024
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAM::PairEAM()
|
||||
{
|
||||
nmax = 0;
|
||||
rho = NULL;
|
||||
fp = NULL;
|
||||
|
||||
ntables = 0;
|
||||
tables = NULL;
|
||||
frho = NULL;
|
||||
frho_0 = NULL;
|
||||
|
||||
// set rhor to NULL so memory deallocation will work
|
||||
// even from derived classes that don't use rhor
|
||||
|
||||
rhor = NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free all arrays
|
||||
check if allocated, since class can be destructed when incomplete
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
PairEAM::~PairEAM()
|
||||
{
|
||||
memory->sfree(rho);
|
||||
memory->sfree(fp);
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy_2d_int_array(setflag);
|
||||
memory->destroy_2d_double_array(cutsq);
|
||||
memory->destroy_2d_int_array(tabindex);
|
||||
}
|
||||
|
||||
for (int m = 0; m < ntables; m++) {
|
||||
delete [] tables[m].filename;
|
||||
delete [] tables[m].frho;
|
||||
delete [] tables[m].rhor;
|
||||
delete [] tables[m].zr;
|
||||
delete [] tables[m].z2r;
|
||||
}
|
||||
memory->sfree(tables);
|
||||
|
||||
if (frho) {
|
||||
memory->destroy_2d_double_array(frho);
|
||||
memory->destroy_2d_double_array(rhor);
|
||||
memory->destroy_2d_double_array(zrtmp);
|
||||
memory->destroy_3d_double_array(z2r);
|
||||
}
|
||||
|
||||
if (frho_0) interpolate_deallocate();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,m,numneigh,itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz;
|
||||
double rsq,r,p,fforce,rhoip,rhojp,z2,z2p,recip,phi,phip,psip;
|
||||
int *neighs;
|
||||
double **f;
|
||||
|
||||
// grow energy array if necessary
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
memory->sfree(rho);
|
||||
memory->sfree(fp);
|
||||
nmax = atom->nmax;
|
||||
rho = (double *) memory->smalloc(nmax*sizeof(double),"eam:rho");
|
||||
fp = (double *) memory->smalloc(nmax*sizeof(double),"eam:fp");
|
||||
}
|
||||
|
||||
eng_vdwl = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) f = update->f_pair;
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
// zero out density
|
||||
|
||||
if (newton_pair) {
|
||||
m = nlocal + atom->nghost;
|
||||
for (i = 0; i < m; i++) rho[i] = 0.0;
|
||||
} else for (i = 0; i < nlocal; i++) rho[i] = 0.0;
|
||||
|
||||
// rho = density at each atom
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
jtype = type[j];
|
||||
p = sqrt(rsq)*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
rho[i] += ((rhor_3[jtype][m]*p + rhor_2[jtype][m])*p +
|
||||
rhor_1[jtype][m])*p + rhor_0[jtype][m];
|
||||
if (newton_pair || j < nlocal)
|
||||
rho[j] += ((rhor_3[itype][m]*p + rhor_2[itype][m])*p +
|
||||
rhor_1[itype][m])*p + rhor_0[itype][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// communicate and sum densities
|
||||
|
||||
if (newton_pair) comm->reverse_comm_pair(this);
|
||||
|
||||
// fp = derivative of embedding energy at each atom
|
||||
// phi = embedding energy at each atom
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
itype = type[i];
|
||||
p = rho[i]*rdrho + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MAX(1,MIN(m,nrho-1));
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
fp[i] = (frho_6[itype][m]*p + frho_5[itype][m])*p + frho_4[itype][m];
|
||||
if (eflag) {
|
||||
phi = ((frho_3[itype][m]*p + frho_2[itype][m])*p +
|
||||
frho_1[itype][m])*p + frho_0[itype][m];
|
||||
eng_vdwl += phi;
|
||||
}
|
||||
}
|
||||
|
||||
// communicate derivative of embedding function
|
||||
|
||||
comm->comm_pair(this);
|
||||
|
||||
// compute forces on each atom
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
jtype = type[j];
|
||||
r = sqrt(rsq);
|
||||
p = r*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
|
||||
// rhoip = derivative of (density at atom j due to atom i)
|
||||
// rhojp = derivative of (density at atom i due to atom j)
|
||||
// phi = pair potential energy
|
||||
// phip = phi'
|
||||
// z2 = phi * r
|
||||
// z2p = (phi * r)' = (phi' r) + phi
|
||||
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
|
||||
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
|
||||
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
|
||||
|
||||
rhoip = (rhor_6[itype][m]*p + rhor_5[itype][m])*p +
|
||||
rhor_4[itype][m];
|
||||
rhojp = (rhor_6[jtype][m]*p + rhor_5[jtype][m])*p +
|
||||
rhor_4[jtype][m];
|
||||
z2 = ((z2r_3[itype][jtype][m]*p + z2r_2[itype][jtype][m])*p +
|
||||
z2r_1[itype][jtype][m])*p + z2r_0[itype][jtype][m];
|
||||
z2p = (z2r_6[itype][jtype][m]*p + z2r_5[itype][jtype][m])*p +
|
||||
z2r_4[itype][jtype][m];
|
||||
|
||||
recip = 1.0/r;
|
||||
phi = z2*recip;
|
||||
phip = z2p*recip - phi*recip;
|
||||
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
|
||||
fforce = psip*recip;
|
||||
f[i][0] -= delx*fforce;
|
||||
f[i][1] -= dely*fforce;
|
||||
f[i][2] -= delz*fforce;
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] += delx*fforce;
|
||||
f[j][1] += dely*fforce;
|
||||
f[j][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (newton_pair || j < nlocal) eng_vdwl += phi;
|
||||
else eng_vdwl += 0.5*phi;
|
||||
}
|
||||
|
||||
if (vflag == 1) {
|
||||
if (newton_pair || j < nlocal) {
|
||||
virial[0] -= delx*delx*fforce;
|
||||
virial[1] -= dely*dely*fforce;
|
||||
virial[2] -= delz*delz*fforce;
|
||||
virial[3] -= delx*dely*fforce;
|
||||
virial[4] -= delx*delz*fforce;
|
||||
virial[5] -= dely*delz*fforce;
|
||||
} else {
|
||||
virial[0] -= 0.5*delx*delx*fforce;
|
||||
virial[1] -= 0.5*dely*dely*fforce;
|
||||
virial[2] -= 0.5*delz*delz*fforce;
|
||||
virial[3] -= 0.5*delx*dely*fforce;
|
||||
virial[4] -= 0.5*delx*delz*fforce;
|
||||
virial[5] -= 0.5*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) virial_compute();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
|
||||
tabindex = memory->create_2d_int_array(n+1,n+1,"pair:tabindex");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg > 0) error->all("Illegal pair_style command");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
reading multiple funcfl files defines a funcfl alloy simulation
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::coeff(int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (narg != 3) error->all("Incorrect args for pair coefficients");
|
||||
|
||||
// parse pair of atom types
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
// read funcfl file only for i,i pairs
|
||||
// only setflag i,i will be set
|
||||
// set mass of each atom type
|
||||
|
||||
int itable;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
if (i == j) {
|
||||
itable = read_funcfl(arg[2]);
|
||||
atom->set_mass(i,tables[itable].mass);
|
||||
tabindex[i][i] = itable;
|
||||
setflag[i][i] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairEAM::init_one(int i, int j)
|
||||
{
|
||||
// only setflag I,I was set by coeff
|
||||
// mixing will occur in init_style if both I,I and J,J were set
|
||||
|
||||
if (setflag[i][i] == 0 || setflag[j][j] == 0)
|
||||
error->all("All EAM pair coeffs are not set");
|
||||
|
||||
// EAM has only one cutoff = max of all pairwise cutoffs
|
||||
// determine max by checking table assigned to all type pairs
|
||||
// only setflag[i][j] = 1 is relevant (if hybrid, some may not be set)
|
||||
|
||||
cutmax = 0.0;
|
||||
for (int ii = 1; ii <= atom->ntypes; ii++) {
|
||||
for (int jj = ii; jj <= atom->ntypes; jj++) {
|
||||
if (setflag[ii][jj] == 0) continue;
|
||||
cutmax = MAX(cutmax,tables[tabindex[ii][jj]].cut);
|
||||
}
|
||||
}
|
||||
|
||||
return cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::init_style()
|
||||
{
|
||||
// set communication sizes in comm class
|
||||
|
||||
comm->maxforward_pair = MAX(comm->maxforward_pair,1);
|
||||
comm->maxreverse_pair = MAX(comm->maxreverse_pair,1);
|
||||
|
||||
// convert read-in funcfl tables to multi-type setfl format and mix I,J
|
||||
// interpolate final spline coeffs
|
||||
|
||||
convert_funcfl();
|
||||
interpolate();
|
||||
|
||||
cutforcesq = cutmax*cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read potential values from a single element EAM file
|
||||
read values into table and bcast values
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int PairEAM::read_funcfl(char *file)
|
||||
{
|
||||
// check if same file has already been read
|
||||
// if yes, return index of table entry
|
||||
// if no, extend table list
|
||||
|
||||
for (int i = 0; i < ntables; i++)
|
||||
if (strcmp(file,tables->filename) == 0) return i;
|
||||
|
||||
tables = (Table *)
|
||||
memory->srealloc(tables,(ntables+1)*sizeof(Table),"pair:tables");
|
||||
|
||||
Table *tb = &tables[ntables];
|
||||
int n = strlen(file) + 1;
|
||||
tb->filename = new char[n];
|
||||
strcpy(tb->filename,file);
|
||||
tb->ith = tb->jth = 0;
|
||||
|
||||
// open potential file
|
||||
|
||||
int me = comm->me;
|
||||
FILE *fp;
|
||||
char line[MAXLINE];
|
||||
|
||||
if (me == 0) {
|
||||
fp = fopen(file,"r");
|
||||
if (fp == NULL) {
|
||||
char str[128];
|
||||
sprintf(str,"Cannot open EAM potential file %s",file);
|
||||
error->one(str);
|
||||
}
|
||||
}
|
||||
|
||||
// read and broadcast header
|
||||
|
||||
int tmp;
|
||||
if (me == 0) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg",&tmp,&tb->mass);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg %d %lg %lg",
|
||||
&tb->nrho,&tb->drho,&tb->nr,&tb->dr,&tb->cut);
|
||||
}
|
||||
|
||||
MPI_Bcast(&tb->mass,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->nrho,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->drho,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->nr,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->dr,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->cut,1,MPI_DOUBLE,0,world);
|
||||
|
||||
// allocate potential arrays and read/bcast them
|
||||
// set z2r to NULL (setfl array) so it can be deallocated
|
||||
|
||||
tb->frho = new double[tb->nrho+1];
|
||||
tb->zr = new double[tb->nr+1];
|
||||
tb->rhor = new double[tb->nr+1];
|
||||
tb->z2r = NULL;
|
||||
|
||||
if (me == 0) grab(fp,tb->nrho,&tb->frho[1]);
|
||||
MPI_Bcast(&tb->frho[1],tb->nrho,MPI_DOUBLE,0,world);
|
||||
|
||||
if (me == 0) grab(fp,tb->nr,&tb->zr[1]);
|
||||
MPI_Bcast(&tb->zr[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
|
||||
if (me == 0) grab(fp,tb->nr,&tb->rhor[1]);
|
||||
MPI_Bcast(&tb->rhor[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
|
||||
// close the potential file
|
||||
|
||||
if (me == 0) fclose(fp);
|
||||
|
||||
ntables++;
|
||||
return ntables-1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert read-in funcfl potentials to multi-type setfl format
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::convert_funcfl()
|
||||
{
|
||||
int i,j,k,m;
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
// determine max values for all i,i type pairs
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
|
||||
double rmax,rhomax;
|
||||
dr = drho = rmax = rhomax = 0.0;
|
||||
|
||||
for (int i = 1; i <= ntypes; i++) {
|
||||
if (setflag[i][i] == 0) continue;
|
||||
Table *tb = &tables[tabindex[i][i]];
|
||||
dr = MAX(dr,tb->dr);
|
||||
drho = MAX(drho,tb->drho);
|
||||
rmax = MAX(rmax,(tb->nr-1) * tb->dr);
|
||||
rhomax = MAX(rhomax,(tb->nrho-1) * tb->drho);
|
||||
}
|
||||
|
||||
// set nr,nrho from cutoff and spacings
|
||||
// 0.5 is for round-off in divide
|
||||
|
||||
nr = static_cast<int> (rmax/dr + 0.5);
|
||||
nrho = static_cast<int> (rhomax/drho + 0.5);
|
||||
|
||||
// allocate multi-type setfl arrays
|
||||
|
||||
if (frho) {
|
||||
memory->destroy_2d_double_array(frho);
|
||||
memory->destroy_2d_double_array(rhor);
|
||||
memory->destroy_2d_double_array(zrtmp);
|
||||
memory->destroy_3d_double_array(z2r);
|
||||
}
|
||||
|
||||
frho = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nrho+1,"eam:frho");
|
||||
rhor = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nr+1,"eam:rhor");
|
||||
zrtmp = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nr+1,"eam:zrtmp");
|
||||
z2r = (double ***)
|
||||
memory->create_3d_double_array(ntypes+1,ntypes+1,nr+1,"eam:frho");
|
||||
|
||||
// interpolate all potentials to a single grid and cutoff for all atom types
|
||||
// frho,rhor are 1:ntypes, z2r is 1:ntypes,1:ntypes
|
||||
// skip if setflag i,i or j,j = 0 (if hybrid, some may not be set)
|
||||
|
||||
double r,p,cof1,cof2,cof3,cof4;
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
if (setflag[i][i] == 0) continue;
|
||||
Table *tb = &tables[tabindex[i][i]];
|
||||
for (m = 1; m <= nrho; m++) {
|
||||
r = (m-1)*drho;
|
||||
p = r/tb->drho + 1.0;
|
||||
k = static_cast<int> (p);
|
||||
k = MIN(k,tb->nrho-2);
|
||||
k = MAX(k,2);
|
||||
p -= k;
|
||||
p = MIN(p,2.0);
|
||||
cof1 = -0.166666667*p*(p-1.0)*(p-2.0);
|
||||
cof2 = 0.5*(p*p-1.0)*(p-2.0);
|
||||
cof3 = -0.5*p*(p+1.0)*(p-2.0);
|
||||
cof4 = 0.166666667*p*(p*p-1.0);
|
||||
frho[i][m] = cof1*tb->frho[k-1] + cof2*tb->frho[k] +
|
||||
cof3*tb->frho[k+1] + cof4*tb->frho[k+2];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
if (setflag[i][i] == 0) continue;
|
||||
Table *tb = &tables[tabindex[i][i]];
|
||||
for (m = 1; m <= nr; m++) {
|
||||
r = (m-1)*dr;
|
||||
p = r/tb->dr + 1.0;
|
||||
k = static_cast<int> (p);
|
||||
k = MIN(k,tb->nr-2);
|
||||
k = MAX(k,2);
|
||||
p -= k;
|
||||
p = MIN(p,2.0);
|
||||
cof1 = -0.166666667*p*(p-1.0)*(p-2.0);
|
||||
cof2 = 0.5*(p*p-1.0)*(p-2.0);
|
||||
cof3 = -0.5*p*(p+1.0)*(p-2.0);
|
||||
cof4 = 0.166666667*p*(p*p-1.0);
|
||||
rhor[i][m] = cof1*tb->rhor[k-1] + cof2*tb->rhor[k] +
|
||||
cof3*tb->rhor[k+1] + cof4*tb->rhor[k+2];
|
||||
zrtmp[i][m] = cof1*tb->zr[k-1] + cof2*tb->zr[k] +
|
||||
cof3*tb->zr[k+1] + cof4*tb->zr[k+2];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
for (j = i; j <= ntypes; j++) {
|
||||
if (setflag[i][i] == 0 || setflag[j][j] == 0) continue;
|
||||
for (m = 1; m <= nr; m++)
|
||||
z2r[i][j][m] = 27.2*0.529 * zrtmp[i][m]*zrtmp[j][m];
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
interpolate EAM potentials
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::interpolate()
|
||||
{
|
||||
// free memory from previous interpolation
|
||||
|
||||
if (frho_0) interpolate_deallocate();
|
||||
|
||||
// interpolation spacings
|
||||
|
||||
rdr = 1.0/dr;
|
||||
rdrho = 1.0/drho;
|
||||
|
||||
// allocate coeff arrays
|
||||
|
||||
int n = atom->ntypes;
|
||||
|
||||
frho_0 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_0");
|
||||
frho_1 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_1");
|
||||
frho_2 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_2");
|
||||
frho_3 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_3");
|
||||
frho_4 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_4");
|
||||
frho_5 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_5");
|
||||
frho_6 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_6");
|
||||
|
||||
rhor_0 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_0");
|
||||
rhor_1 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_1");
|
||||
rhor_2 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_2");
|
||||
rhor_3 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_3");
|
||||
rhor_4 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_4");
|
||||
rhor_5 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_5");
|
||||
rhor_6 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_6");
|
||||
|
||||
z2r_0 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_0");
|
||||
z2r_1 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_1");
|
||||
z2r_2 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_2");
|
||||
z2r_3 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_3");
|
||||
z2r_4 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_4");
|
||||
z2r_5 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_5");
|
||||
z2r_6 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_6");
|
||||
|
||||
// frho interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
// if skip, set frho arrays to 0.0, since they will still be accessed
|
||||
// for non-EAM atoms when compute() calculates embedding function
|
||||
|
||||
int i,j,m;
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
if (setflag[i][i] == 0) {
|
||||
for (j = 1; j <= n; j++)
|
||||
for (m = 1; m <= nrho; m++)
|
||||
frho_0[j][m] = frho_1[j][m] = frho_2[j][m] = frho_3[j][m] =
|
||||
frho_4[j][m] = frho_5[j][m] = frho_6[j][m] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nrho; m++) frho_0[i][m] = frho[i][m];
|
||||
|
||||
frho_1[i][1] = frho_0[i][2]-frho_0[i][1];
|
||||
frho_1[i][2] = 0.5*(frho_0[i][3]-frho_0[i][1]);
|
||||
frho_1[i][nrho-1] = 0.5*(frho_0[i][nrho]-frho_0[i][nrho-2]);
|
||||
frho_1[i][nrho] = frho_0[i][nrho]-frho_0[i][nrho-1];
|
||||
|
||||
for (m = 3; m <= nrho-2; m++)
|
||||
frho_1[i][m] = ((frho_0[i][m-2]-frho_0[i][m+2]) +
|
||||
8.0*(frho_0[i][m+1]-frho_0[i][m-1]))/12.0;
|
||||
|
||||
for (m = 1; m <= nrho-1; m++) {
|
||||
frho_2[i][m] = 3.*(frho_0[i][m+1]-frho_0[i][m]) -
|
||||
2.0*frho_1[i][m] - frho_1[i][m+1];
|
||||
frho_3[i][m] = frho_1[i][m] + frho_1[i][m+1] -
|
||||
2.0*(frho_0[i][m+1]-frho_0[i][m]);
|
||||
}
|
||||
|
||||
frho_2[i][nrho] = 0.0;
|
||||
frho_3[i][nrho] = 0.0;
|
||||
|
||||
for (m = 1; m <= nrho; m++) {
|
||||
frho_4[i][m] = frho_1[i][m]/drho;
|
||||
frho_5[i][m] = 2.0*frho_2[i][m]/drho;
|
||||
frho_6[i][m] = 3.0*frho_3[i][m]/drho;
|
||||
}
|
||||
}
|
||||
|
||||
// rhor interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
if (setflag[i][i] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) rhor_0[i][m] = rhor[i][m];
|
||||
|
||||
rhor_1[i][1] = rhor_0[i][2]-rhor_0[i][1];
|
||||
rhor_1[i][2] = 0.5*(rhor_0[i][3]-rhor_0[i][1]);
|
||||
rhor_1[i][nr-1] = 0.5*(rhor_0[i][nr]-rhor_0[i][nr-2]);
|
||||
rhor_1[i][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
rhor_1[i][m] = ((rhor_0[i][m-2]-rhor_0[i][m+2]) +
|
||||
8.0*(rhor_0[i][m+1]-rhor_0[i][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
rhor_2[i][m] = 3.0*(rhor_0[i][m+1]-rhor_0[i][m]) -
|
||||
2.0*rhor_1[i][m] - rhor_1[i][m+1];
|
||||
rhor_3[i][m] = rhor_1[i][m] + rhor_1[i][m+1] -
|
||||
2.0*(rhor_0[i][m+1]-rhor_0[i][m]);
|
||||
}
|
||||
|
||||
rhor_2[i][nr] = 0.0;
|
||||
rhor_3[i][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
rhor_4[i][m] = rhor_1[i][m]/dr;
|
||||
rhor_5[i][m] = 2.0*rhor_2[i][m]/dr;
|
||||
rhor_6[i][m] = 3.0*rhor_3[i][m]/dr;
|
||||
}
|
||||
}
|
||||
|
||||
// z2r interpolation for 1:ntypes,1:ntypes
|
||||
// skip if setflag i,i or j,j = 0 (if hybrid, some may not be set)
|
||||
// set j,i coeffs = i,j coeffs
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (setflag[i][i] == 0 || setflag[j][j] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) z2r_0[i][j][m] = z2r[i][j][m];
|
||||
|
||||
z2r_1[i][j][1] = z2r_0[i][j][2]-z2r_0[i][j][1];
|
||||
z2r_1[i][j][2] = 0.5*(z2r_0[i][j][3]-z2r_0[i][j][1]);
|
||||
z2r_1[i][j][nr-1] = 0.5*(z2r_0[i][j][nr]-z2r_0[i][j][nr-2]);
|
||||
z2r_1[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
z2r_1[i][j][m] = ((z2r_0[i][j][m-2]-z2r_0[i][j][m+2]) +
|
||||
8.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
z2r_2[i][j][m] = 3.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]) -
|
||||
2.0*z2r_1[i][j][m] - z2r_1[i][j][m+1];
|
||||
z2r_3[i][j][m] = z2r_1[i][j][m] + z2r_1[i][j][m+1] -
|
||||
2.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]);
|
||||
}
|
||||
|
||||
z2r_2[i][j][nr] = 0.0;
|
||||
z2r_3[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_4[i][j][m] = z2r_1[i][j][m]/dr;
|
||||
z2r_5[i][j][m] = 2.0*z2r_2[i][j][m]/dr;
|
||||
z2r_6[i][j][m] = 3.0*z2r_3[i][j][m]/dr;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_0[j][i][m] = z2r_0[i][j][m];
|
||||
z2r_1[j][i][m] = z2r_1[i][j][m];
|
||||
z2r_2[j][i][m] = z2r_2[i][j][m];
|
||||
z2r_3[j][i][m] = z2r_3[i][j][m];
|
||||
z2r_4[j][i][m] = z2r_4[i][j][m];
|
||||
z2r_5[j][i][m] = z2r_5[i][j][m];
|
||||
z2r_6[j][i][m] = z2r_6[i][j][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
grab n values from file fp and put them in list
|
||||
values can be several to a line
|
||||
only called by proc 0
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::grab(FILE *fp, int n, double *list)
|
||||
{
|
||||
char *ptr;
|
||||
char line[MAXLINE];
|
||||
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
ptr = strtok(line," \t\n\r\f");
|
||||
list[i++] = atof(ptr);
|
||||
while (ptr = strtok(NULL," \t\n\r\f")) list[i++] = atof(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
skip n values from file fp
|
||||
values can be several to a line
|
||||
only called by proc 0
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::skip(FILE *fp, int n)
|
||||
{
|
||||
char line[MAXLINE];
|
||||
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
strtok(line," \t\n\r\f");
|
||||
i++;
|
||||
while (strtok(NULL," \t\n\r\f")) i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
deallocate spline interpolation arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::interpolate_deallocate()
|
||||
{
|
||||
memory->destroy_2d_double_array(frho_0);
|
||||
memory->destroy_2d_double_array(frho_1);
|
||||
memory->destroy_2d_double_array(frho_2);
|
||||
memory->destroy_2d_double_array(frho_3);
|
||||
memory->destroy_2d_double_array(frho_4);
|
||||
memory->destroy_2d_double_array(frho_5);
|
||||
memory->destroy_2d_double_array(frho_6);
|
||||
|
||||
memory->destroy_2d_double_array(rhor_0);
|
||||
memory->destroy_2d_double_array(rhor_1);
|
||||
memory->destroy_2d_double_array(rhor_2);
|
||||
memory->destroy_2d_double_array(rhor_3);
|
||||
memory->destroy_2d_double_array(rhor_4);
|
||||
memory->destroy_2d_double_array(rhor_5);
|
||||
memory->destroy_2d_double_array(rhor_6);
|
||||
|
||||
memory->destroy_3d_double_array(z2r_0);
|
||||
memory->destroy_3d_double_array(z2r_1);
|
||||
memory->destroy_3d_double_array(z2r_2);
|
||||
memory->destroy_3d_double_array(z2r_3);
|
||||
memory->destroy_3d_double_array(z2r_4);
|
||||
memory->destroy_3d_double_array(z2r_5);
|
||||
memory->destroy_3d_double_array(z2r_6);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::single(int i, int j, int itype, int jtype,
|
||||
double rsq, double factor_coul, double factor_lj,
|
||||
int eflag, One &one)
|
||||
{
|
||||
double r,p,rhoip,rhojp,z2,z2p,recip,phi,phip,psip;
|
||||
int m;
|
||||
|
||||
r = sqrt(rsq);
|
||||
p = r*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
|
||||
rhoip = (rhor_6[itype][m]*p + rhor_5[itype][m])*p +
|
||||
rhor_4[itype][m];
|
||||
rhojp = (rhor_6[jtype][m]*p + rhor_5[jtype][m])*p +
|
||||
rhor_4[jtype][m];
|
||||
z2 = ((z2r_3[itype][jtype][m]*p + z2r_2[itype][jtype][m])*p +
|
||||
z2r_1[itype][jtype][m])*p + z2r_0[itype][jtype][m];
|
||||
z2p = (z2r_6[itype][jtype][m]*p + z2r_5[itype][jtype][m])*p +
|
||||
z2r_4[itype][jtype][m];
|
||||
|
||||
recip = 1.0/r;
|
||||
phi = z2*recip;
|
||||
phip = z2p*recip - phi*recip;
|
||||
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
|
||||
one.fforce = -psip*recip;
|
||||
|
||||
if (eflag) {
|
||||
one.eng_vdwl = phi;
|
||||
one.eng_coul = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::single_embed(int i, int itype, double &fpi,
|
||||
int eflag, double &phi)
|
||||
{
|
||||
double p = rho[i]*rdrho + 1.0;
|
||||
int m = static_cast<int> (p);
|
||||
m = MAX(1,MIN(m,nrho-1));
|
||||
p -= m;
|
||||
|
||||
fpi = (frho_6[itype][m]*p + frho_5[itype][m])*p + frho_4[itype][m];
|
||||
if (eflag)
|
||||
phi = ((frho_3[itype][m]*p + frho_2[itype][m])*p +
|
||||
frho_1[itype][m])*p + frho_0[itype][m];
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int PairEAM::pack_comm(int n, int *list, double *buf, int *pbc_flags)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = fp[j];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) fp[i] = buf[m++];
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int PairEAM::pack_reverse_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) buf[m++] = rho[i];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAM::unpack_reverse_comm(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
rho[j] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int PairEAM::memory_usage()
|
||||
{
|
||||
int bytes = 2 * nmax * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
@ -1,472 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Stephen Foiles (SNL), Murray Daw (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "pair_eam_alloy.h"
|
||||
#include "atom.h"
|
||||
#include "force.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define MAXLINE 1024
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAMAlloy::PairEAMAlloy()
|
||||
{
|
||||
one_coeff = 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAlloy::coeff(int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (narg != 3 + atom->ntypes)
|
||||
error->all("Incorrect args for pair coefficients");
|
||||
|
||||
// insure I,J args are * *
|
||||
|
||||
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
|
||||
error->all("Incorrect args for pair coefficients");
|
||||
|
||||
// read EAM setfl file, possibly multiple times
|
||||
// first clear setflag since are doing this once for I,J = *,*
|
||||
// read for all i,j pairs where ith,jth mapping is non-zero
|
||||
// set setflag i,j for non-zero pairs
|
||||
// set mass of atom type if i = j
|
||||
|
||||
int n = atom->ntypes;
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
int itable,ith,jth;
|
||||
int ilo,ihi,jlo,jhi;
|
||||
ilo = jlo = 1;
|
||||
ihi = jhi = n;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
ith = atoi(arg[2+i]);
|
||||
jth = atoi(arg[2+j]);
|
||||
if (ith > 0 && jth > 0) {
|
||||
itable = read_setfl(arg[2],ith,jth);
|
||||
if (i == j) atom->set_mass(i,tables[itable].mass);
|
||||
tabindex[i][j] = itable;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairEAMAlloy::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0)
|
||||
error->all("All EAM pair coeffs are not set");
|
||||
|
||||
// EAM has only one cutoff = max of all pairwise cutoffs
|
||||
// determine max by checking table assigned to all type pairs
|
||||
// only setflag[i][j] = 1 is relevant (if hybrid, some may not be set)
|
||||
|
||||
cutmax = 0.0;
|
||||
for (int ii = 1; ii <= atom->ntypes; ii++) {
|
||||
for (int jj = ii; jj <= atom->ntypes; jj++) {
|
||||
if (setflag[ii][jj] == 0) continue;
|
||||
cutmax = MAX(cutmax,tables[tabindex[ii][jj]].cut);
|
||||
}
|
||||
}
|
||||
|
||||
return cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAlloy::init_style()
|
||||
{
|
||||
// set communication sizes in comm class
|
||||
|
||||
comm->maxforward_pair = MAX(comm->maxforward_pair,1);
|
||||
comm->maxreverse_pair = MAX(comm->maxreverse_pair,1);
|
||||
|
||||
// copy read-in-tables to multi-type setfl format
|
||||
// interpolate final spline coeffs
|
||||
|
||||
store_setfl();
|
||||
interpolate();
|
||||
|
||||
cutforcesq = cutmax*cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read ith,jth potential values from a multi-element alloy EAM file
|
||||
read values into table and bcast values
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int PairEAMAlloy::read_setfl(char *file, int ith, int jth)
|
||||
{
|
||||
// check if ith,jth portion of same file has already been read
|
||||
// if yes, return index of table entry
|
||||
// if no, extend table list
|
||||
|
||||
for (int i = 0; i < ntables; i++)
|
||||
if (ith == tables[i].ith && jth == tables[i].jth) return i;
|
||||
|
||||
tables = (Table *)
|
||||
memory->srealloc(tables,(ntables+1)*sizeof(Table),"pair:tables");
|
||||
|
||||
Table *tb = &tables[ntables];
|
||||
int n = strlen(file) + 1;
|
||||
tb->filename = new char[n];
|
||||
strcpy(tb->filename,file);
|
||||
tb->ith = ith;
|
||||
tb->jth = jth;
|
||||
|
||||
// open potential file
|
||||
|
||||
int me = comm->me;
|
||||
FILE *fp;
|
||||
char line[MAXLINE];
|
||||
|
||||
if (me == 0) {
|
||||
fp = fopen(file,"r");
|
||||
if (fp == NULL) {
|
||||
char str[128];
|
||||
sprintf(str,"Cannot open EAM potential file %s",file);
|
||||
error->one(str);
|
||||
}
|
||||
}
|
||||
|
||||
// read and broadcast header
|
||||
|
||||
int ntypes;
|
||||
if (me == 0) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d",&ntypes);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg %d %lg %lg",
|
||||
&tb->nrho,&tb->drho,&tb->nr,&tb->dr,&tb->cut);
|
||||
}
|
||||
|
||||
MPI_Bcast(&ntypes,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->nrho,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->drho,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->nr,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->dr,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->cut,1,MPI_DOUBLE,0,world);
|
||||
|
||||
// check if ith,jth are consistent with ntypes
|
||||
|
||||
if (ith > ntypes || jth > ntypes)
|
||||
error->all("Requested atom types in EAM setfl file do not exist");
|
||||
|
||||
// allocate potential arrays and read/bcast them
|
||||
// skip sections of file that don't correspond to ith,jth
|
||||
// extract mass, frho, rhor for i,i from ith element section
|
||||
// extract z2r for i,j from ith,jth array of z2r section
|
||||
// note that ith can be < or > than jth
|
||||
// set zr to NULL (funcl array) so it can be deallocated
|
||||
|
||||
tb->frho = new double[tb->nrho+1];
|
||||
tb->rhor = new double[tb->nr+1];
|
||||
tb->z2r = new double[tb->nr+1];
|
||||
tb->zr = NULL;
|
||||
|
||||
int i,j,tmp;
|
||||
double mass;
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
if (me == 0) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg",&tmp,&mass);
|
||||
}
|
||||
MPI_Bcast(&mass,1,MPI_DOUBLE,0,world);
|
||||
|
||||
if (i == ith && ith == jth) {
|
||||
tb->mass = mass;
|
||||
if (me == 0) grab(fp,tb->nrho,&tb->frho[1]);
|
||||
MPI_Bcast(&tb->frho[1],tb->nrho,MPI_DOUBLE,0,world);
|
||||
if (me == 0) grab(fp,tb->nr,&tb->rhor[1]);
|
||||
MPI_Bcast(&tb->rhor[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
} else {
|
||||
if (me == 0) skip(fp,tb->nrho);
|
||||
if (me == 0) skip(fp,tb->nr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
for (j = 1; j <= i; j++) {
|
||||
if ((i == ith && j == jth) || (j == ith && i == jth)) {
|
||||
if (me == 0) grab(fp,tb->nr,&tb->z2r[1]);
|
||||
MPI_Bcast(&tb->z2r[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
} else if (me == 0) skip(fp,tb->nr);
|
||||
}
|
||||
}
|
||||
|
||||
// close the potential file
|
||||
|
||||
if (me == 0) fclose(fp);
|
||||
|
||||
ntables++;
|
||||
return ntables-1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
store read-in setfl values in multi-type setfl format
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAlloy::store_setfl()
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
// set nrho,nr,drho,dr from any i,i table entry since all the same
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
if (setflag[i][i]) break;
|
||||
|
||||
nrho = tables[tabindex[i][i]].nrho;
|
||||
nr = tables[tabindex[i][i]].nr;
|
||||
drho = tables[tabindex[i][i]].drho;
|
||||
dr = tables[tabindex[i][i]].dr;
|
||||
|
||||
// allocate multi-type setfl arrays
|
||||
|
||||
if (frho) {
|
||||
memory->destroy_2d_double_array(frho);
|
||||
memory->destroy_2d_double_array(rhor);
|
||||
memory->destroy_2d_double_array(zrtmp);
|
||||
memory->destroy_3d_double_array(z2r);
|
||||
}
|
||||
|
||||
frho = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nrho+1,"eam:frho");
|
||||
rhor = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nr+1,"eam:rhor");
|
||||
zrtmp = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nr+1,"eam:zrtmp");
|
||||
z2r = (double ***)
|
||||
memory->create_3d_double_array(ntypes+1,ntypes+1,nr+1,"eam:frho");
|
||||
|
||||
// copy from read-in tables to multi-type setfl arrays
|
||||
// frho,rhor are 1:ntypes, z2r is 1:ntypes,1:ntypes
|
||||
// skip if setflag i,j = 0 (if hybrid, some may not be set)
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
for (j = i; j <= ntypes; j++) {
|
||||
if (setflag[i][j] == 0) continue;
|
||||
Table *tb = &tables[tabindex[i][j]];
|
||||
if (i == j) {
|
||||
for (m = 1; m <= nrho; m++) frho[i][m] = tb->frho[m];
|
||||
for (m = 1; m <= nr; m++) rhor[i][m] = tb->rhor[m];
|
||||
}
|
||||
for (m = 1; m <= nr; m++) z2r[i][j][m] = tb->z2r[m];
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
interpolate EAM potentials
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMAlloy::interpolate()
|
||||
{
|
||||
// free memory from previous interpolation
|
||||
|
||||
if (frho_0) interpolate_deallocate();
|
||||
|
||||
// interpolation spacings
|
||||
|
||||
rdr = 1.0/dr;
|
||||
rdrho = 1.0/drho;
|
||||
|
||||
// allocate coeff arrays
|
||||
|
||||
int n = atom->ntypes;
|
||||
|
||||
frho_0 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_0");
|
||||
frho_1 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_1");
|
||||
frho_2 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_2");
|
||||
frho_3 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_3");
|
||||
frho_4 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_4");
|
||||
frho_5 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_5");
|
||||
frho_6 = memory->create_2d_double_array(n+1,nrho+1,"eam:frho_6");
|
||||
|
||||
rhor_0 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_0");
|
||||
rhor_1 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_1");
|
||||
rhor_2 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_2");
|
||||
rhor_3 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_3");
|
||||
rhor_4 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_4");
|
||||
rhor_5 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_5");
|
||||
rhor_6 = memory->create_2d_double_array(n+1,nr+1,"eam:rhor_6");
|
||||
|
||||
z2r_0 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_0");
|
||||
z2r_1 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_1");
|
||||
z2r_2 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_2");
|
||||
z2r_3 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_3");
|
||||
z2r_4 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_4");
|
||||
z2r_5 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_5");
|
||||
z2r_6 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam:z2r_6");
|
||||
|
||||
// frho interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
// if skip, set frho arrays to 0.0, since they will still be accessed
|
||||
// for non-EAM atoms when compute() calculates embedding function
|
||||
|
||||
int i,j,m;
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
if (setflag[i][i] == 0) {
|
||||
for (m = 1; m <= nrho; m++)
|
||||
frho_0[i][m] = frho_1[i][m] = frho_2[i][m] = frho_3[i][m] =
|
||||
frho_4[i][m] = frho_5[i][m] = frho_6[i][m] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nrho; m++) frho_0[i][m] = frho[i][m];
|
||||
|
||||
frho_1[i][1] = frho_0[i][2]-frho_0[i][1];
|
||||
frho_1[i][2] = 0.5*(frho_0[i][3]-frho_0[i][1]);
|
||||
frho_1[i][nrho-1] = 0.5*(frho_0[i][nrho]-frho_0[i][nrho-2]);
|
||||
frho_1[i][nrho] = frho_0[i][nrho]-frho_0[i][nrho-1];
|
||||
|
||||
for (m = 3; m <= nrho-2; m++)
|
||||
frho_1[i][m] = ((frho_0[i][m-2]-frho_0[i][m+2]) +
|
||||
8.0*(frho_0[i][m+1]-frho_0[i][m-1]))/12.0;
|
||||
|
||||
for (m = 1; m <= nrho-1; m++) {
|
||||
frho_2[i][m] = 3.*(frho_0[i][m+1]-frho_0[i][m]) -
|
||||
2.0*frho_1[i][m] - frho_1[i][m+1];
|
||||
frho_3[i][m] = frho_1[i][m] + frho_1[i][m+1] -
|
||||
2.0*(frho_0[i][m+1]-frho_0[i][m]);
|
||||
}
|
||||
|
||||
frho_2[i][nrho] = 0.0;
|
||||
frho_3[i][nrho] = 0.0;
|
||||
|
||||
for (m = 1; m <= nrho; m++) {
|
||||
frho_4[i][m] = frho_1[i][m]/drho;
|
||||
frho_5[i][m] = 2.0*frho_2[i][m]/drho;
|
||||
frho_6[i][m] = 3.0*frho_3[i][m]/drho;
|
||||
}
|
||||
}
|
||||
|
||||
// rhor interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
if (setflag[i][i] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) rhor_0[i][m] = rhor[i][m];
|
||||
|
||||
rhor_1[i][1] = rhor_0[i][2]-rhor_0[i][1];
|
||||
rhor_1[i][2] = 0.5*(rhor_0[i][3]-rhor_0[i][1]);
|
||||
rhor_1[i][nr-1] = 0.5*(rhor_0[i][nr]-rhor_0[i][nr-2]);
|
||||
rhor_1[i][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
rhor_1[i][m] = ((rhor_0[i][m-2]-rhor_0[i][m+2]) +
|
||||
8.0*(rhor_0[i][m+1]-rhor_0[i][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
rhor_2[i][m] = 3.0*(rhor_0[i][m+1]-rhor_0[i][m]) -
|
||||
2.0*rhor_1[i][m] - rhor_1[i][m+1];
|
||||
rhor_3[i][m] = rhor_1[i][m] + rhor_1[i][m+1] -
|
||||
2.0*(rhor_0[i][m+1]-rhor_0[i][m]);
|
||||
}
|
||||
|
||||
rhor_2[i][nr] = 0.0;
|
||||
rhor_3[i][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
rhor_4[i][m] = rhor_1[i][m]/dr;
|
||||
rhor_5[i][m] = 2.0*rhor_2[i][m]/dr;
|
||||
rhor_6[i][m] = 3.0*rhor_3[i][m]/dr;
|
||||
}
|
||||
}
|
||||
|
||||
// z2r interpolation for 1:ntypes,1:ntypes
|
||||
// skip if setflag i,j = 0 (if hybrid, some may not be set)
|
||||
// set j,i coeffs = i,j coeffs
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (setflag[i][j] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) z2r_0[i][j][m] = z2r[i][j][m];
|
||||
|
||||
z2r_1[i][j][1] = z2r_0[i][j][2]-z2r_0[i][j][1];
|
||||
z2r_1[i][j][2] = 0.5*(z2r_0[i][j][3]-z2r_0[i][j][1]);
|
||||
z2r_1[i][j][nr-1] = 0.5*(z2r_0[i][j][nr]-z2r_0[i][j][nr-2]);
|
||||
z2r_1[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
z2r_1[i][j][m] = ((z2r_0[i][j][m-2]-z2r_0[i][j][m+2]) +
|
||||
8.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
z2r_2[i][j][m] = 3.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]) -
|
||||
2.0*z2r_1[i][j][m] - z2r_1[i][j][m+1];
|
||||
z2r_3[i][j][m] = z2r_1[i][j][m] + z2r_1[i][j][m+1] -
|
||||
2.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]);
|
||||
}
|
||||
|
||||
z2r_2[i][j][nr] = 0.0;
|
||||
z2r_3[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_4[i][j][m] = z2r_1[i][j][m]/dr;
|
||||
z2r_5[i][j][m] = 2.0*z2r_2[i][j][m]/dr;
|
||||
z2r_6[i][j][m] = 3.0*z2r_3[i][j][m]/dr;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_0[j][i][m] = z2r_0[i][j][m];
|
||||
z2r_1[j][i][m] = z2r_1[i][j][m];
|
||||
z2r_2[j][i][m] = z2r_2[i][j][m];
|
||||
z2r_3[j][i][m] = z2r_3[i][j][m];
|
||||
z2r_4[j][i][m] = z2r_4[i][j][m];
|
||||
z2r_5[j][i][m] = z2r_5[i][j][m];
|
||||
z2r_6[j][i][m] = z2r_6[i][j][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_EAM_ALLOY_H
|
||||
#define PAIR_EAM_ALLOY_H
|
||||
|
||||
#include "pair_eam.h"
|
||||
|
||||
class PairEAMAlloy : public PairEAM {
|
||||
public:
|
||||
PairEAMAlloy();
|
||||
void coeff(int, char **);
|
||||
double init_one(int, int);
|
||||
void init_style();
|
||||
|
||||
private:
|
||||
int read_setfl(char *, int, int);
|
||||
void store_setfl();
|
||||
void interpolate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,771 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Tim Lau (MIT)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "pair_eam_fs.h"
|
||||
#include "atom.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define MAXLINE 1024
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAMFS::PairEAMFS()
|
||||
{
|
||||
one_coeff = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairEAMFS::~PairEAMFS() {
|
||||
|
||||
// deallocate array unique to derived class, parent will deallocate the rest
|
||||
|
||||
if (frho) memory->destroy_3d_double_array(rhor_fs);
|
||||
|
||||
// insure derived-class's deallocate is called
|
||||
// set ptr to NULL to prevent parent class from calling it's deallocate
|
||||
|
||||
if (frho_0) interpolate_deallocate();
|
||||
frho_0 = NULL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,m,numneigh,itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz;
|
||||
double rsq,r,p,fforce,rhoip,rhojp,z2,z2p,recip,phi,phip,psip;
|
||||
int *neighs;
|
||||
double **f;
|
||||
|
||||
// grow energy array if necessary
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
memory->sfree(rho);
|
||||
memory->sfree(fp);
|
||||
nmax = atom->nmax;
|
||||
rho = (double *) memory->smalloc(nmax*sizeof(double),"eam:rho");
|
||||
fp = (double *) memory->smalloc(nmax*sizeof(double),"eam:fp");
|
||||
}
|
||||
|
||||
eng_vdwl = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) f = update->f_pair;
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
// zero out density
|
||||
|
||||
if (newton_pair) {
|
||||
m = nlocal + atom->nghost;
|
||||
for (i = 0; i < m; i++) rho[i] = 0.0;
|
||||
} else for (i = 0; i < nlocal; i++) rho[i] = 0.0;
|
||||
|
||||
// rho = density at each atom
|
||||
// loop over neighbors of my atoms
|
||||
// FS has type-specific rho functional
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
jtype = type[j];
|
||||
p = sqrt(rsq)*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
rho[i] +=
|
||||
((rhor_fs_3[jtype][itype][m]*p + rhor_fs_2[jtype][itype][m])*p +
|
||||
rhor_fs_1[jtype][itype][m])*p + rhor_fs_0[jtype][itype][m];
|
||||
if (newton_pair || j < nlocal)
|
||||
rho[j] +=
|
||||
((rhor_fs_3[itype][jtype][m]*p + rhor_fs_2[itype][jtype][m])*p +
|
||||
rhor_fs_1[itype][jtype][m])*p + rhor_fs_0[itype][jtype][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// communicate and sum densities
|
||||
|
||||
if (newton_pair) comm->reverse_comm_pair(this);
|
||||
|
||||
// fp = derivative of embedding energy at each atom
|
||||
// phi = embedding energy at each atom
|
||||
// FS is same as standard EAM
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
itype = type[i];
|
||||
p = rho[i]*rdrho + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MAX(1,MIN(m,nrho-1));
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
fp[i] = (frho_6[itype][m]*p + frho_5[itype][m])*p + frho_4[itype][m];
|
||||
if (eflag) {
|
||||
phi = ((frho_3[itype][m]*p + frho_2[itype][m])*p +
|
||||
frho_1[itype][m])*p + frho_0[itype][m];
|
||||
eng_vdwl += phi;
|
||||
}
|
||||
}
|
||||
|
||||
// communicate derivative of embedding function
|
||||
|
||||
comm->comm_pair(this);
|
||||
|
||||
// compute forces on each atom
|
||||
// loop over neighbors of my atoms
|
||||
// FS has type-specific rhoip and rhojp
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cutforcesq) {
|
||||
jtype = type[j];
|
||||
r = sqrt(rsq);
|
||||
p = r*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
|
||||
// rhoip = derivative of (density at atom j due to atom i)
|
||||
// rhojp = derivative of (density at atom i due to atom j)
|
||||
// phi = pair potential energy
|
||||
// phip = phi'
|
||||
// z2 = phi * r
|
||||
// z2p = (phi * r)' = (phi' r) + phi
|
||||
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
|
||||
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
|
||||
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
|
||||
|
||||
rhoip =
|
||||
(rhor_fs_6[itype][jtype][m]*p + rhor_fs_5[itype][jtype][m])*p +
|
||||
rhor_fs_4[itype][jtype][m];
|
||||
rhojp =
|
||||
(rhor_fs_6[jtype][itype][m]*p + rhor_fs_5[jtype][itype][m])*p +
|
||||
rhor_fs_4[jtype][itype][m];
|
||||
z2 = ((z2r_3[itype][jtype][m]*p + z2r_2[itype][jtype][m])*p +
|
||||
z2r_1[itype][jtype][m])*p + z2r_0[itype][jtype][m];
|
||||
z2p = (z2r_6[itype][jtype][m]*p + z2r_5[itype][jtype][m])*p +
|
||||
z2r_4[itype][jtype][m];
|
||||
|
||||
recip = 1.0/r;
|
||||
phi = z2*recip;
|
||||
phip = z2p*recip - phi*recip;
|
||||
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
|
||||
fforce = psip*recip;
|
||||
f[i][0] -= delx*fforce;
|
||||
f[i][1] -= dely*fforce;
|
||||
f[i][2] -= delz*fforce;
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] += delx*fforce;
|
||||
f[j][1] += dely*fforce;
|
||||
f[j][2] += delz*fforce;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (newton_pair || j < nlocal) eng_vdwl += phi;
|
||||
else eng_vdwl += 0.5*phi;
|
||||
}
|
||||
|
||||
if (vflag == 1) {
|
||||
if (newton_pair || j < nlocal) {
|
||||
virial[0] -= delx*delx*fforce;
|
||||
virial[1] -= dely*dely*fforce;
|
||||
virial[2] -= delz*delz*fforce;
|
||||
virial[3] -= delx*dely*fforce;
|
||||
virial[4] -= delx*delz*fforce;
|
||||
virial[5] -= dely*delz*fforce;
|
||||
} else {
|
||||
virial[0] -= 0.5*delx*delx*fforce;
|
||||
virial[1] -= 0.5*dely*dely*fforce;
|
||||
virial[2] -= 0.5*delz*delz*fforce;
|
||||
virial[3] -= 0.5*delx*dely*fforce;
|
||||
virial[4] -= 0.5*delx*delz*fforce;
|
||||
virial[5] -= 0.5*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) virial_compute();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::coeff(int narg, char **arg)
|
||||
{
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (narg != 3 + atom->ntypes)
|
||||
error->all("Incorrect args for pair coefficients");
|
||||
|
||||
// insure I,J args are * *
|
||||
// can only have one file, so clear all setflag settings
|
||||
|
||||
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
|
||||
error->all("Incorrect args for pair coefficients");
|
||||
|
||||
// read Finnis/Sinclair modified setfl file
|
||||
// first clear setflag since are doing this once for I,J = *,*
|
||||
// read for all i,j pairs where ith,jth mapping is non-zero
|
||||
// set setflag i,j for non-zero pairs
|
||||
// set mass of atom type if i = j
|
||||
|
||||
int n = atom->ntypes;
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = 1; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
int itable,ith,jth;
|
||||
int ilo,ihi,jlo,jhi;
|
||||
ilo = jlo = 1;
|
||||
ihi = jhi = n;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = jlo; j <= jhi; j++) {
|
||||
ith = atoi(arg[2+i]);
|
||||
jth = atoi(arg[2+j]);
|
||||
if (ith > 0 && jth > 0) {
|
||||
itable = read_setfl(arg[2],ith,jth);
|
||||
if (i == j) atom->set_mass(i,tables[itable].mass);
|
||||
tabindex[i][j] = itable;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairEAMFS::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0)
|
||||
error->all("All EAM pair coeffs are not set");
|
||||
|
||||
// EAM has only one cutoff = max of all pairwise cutoffs
|
||||
// determine max by checking table assigned to all type pairs
|
||||
// only setflag[i][j] = 1 is relevant (if hybrid, some may not be set)
|
||||
|
||||
cutmax = 0.0;
|
||||
for (int ii = 1; ii <= atom->ntypes; ii++) {
|
||||
for (int jj = ii; jj <= atom->ntypes; jj++) {
|
||||
if (setflag[ii][jj] == 0) continue;
|
||||
cutmax = MAX(cutmax,tables[tabindex[ii][jj]].cut);
|
||||
}
|
||||
}
|
||||
|
||||
return cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::init_style()
|
||||
{
|
||||
// set communication sizes in comm class
|
||||
|
||||
comm->maxforward_pair = MAX(comm->maxforward_pair,1);
|
||||
comm->maxreverse_pair = MAX(comm->maxreverse_pair,1);
|
||||
|
||||
// copy read-in-tables to multi-type setfl format
|
||||
// interpolate final spline coeffs
|
||||
|
||||
store_setfl();
|
||||
interpolate();
|
||||
|
||||
cutforcesq = cutmax*cutmax;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
read ith,jth potential values from a multi-element alloy EAM/FS file
|
||||
read values into table and bcast values
|
||||
this file has different format than standard EAM setfl file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int PairEAMFS::read_setfl(char *file, int ith, int jth)
|
||||
{
|
||||
// check if ith,jth portion of same file has already been read
|
||||
// if yes, return index of table entry
|
||||
// if no, extend table list
|
||||
|
||||
for (int i = 0; i < ntables; i++)
|
||||
if (ith == tables[i].ith && jth == tables[i].jth) return i;
|
||||
|
||||
tables = (Table *)
|
||||
memory->srealloc(tables,(ntables+1)*sizeof(Table),"pair:tables");
|
||||
|
||||
Table *tb = &tables[ntables];
|
||||
int n = strlen(file) + 1;
|
||||
tb->filename = new char[n];
|
||||
strcpy(tb->filename,file);
|
||||
tb->ith = ith;
|
||||
tb->jth = jth;
|
||||
|
||||
// open potential file
|
||||
|
||||
int me = comm->me;
|
||||
FILE *fp;
|
||||
char line[MAXLINE];
|
||||
|
||||
if (me == 0) {
|
||||
fp = fopen(file,"r");
|
||||
if (fp == NULL) {
|
||||
char str[128];
|
||||
sprintf(str,"Cannot open EAM potential file %s",file);
|
||||
error->one(str);
|
||||
}
|
||||
}
|
||||
|
||||
// read and broadcast header
|
||||
|
||||
int ntypes;
|
||||
if (me == 0) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d",&ntypes);
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg %d %lg %lg",
|
||||
&tb->nrho,&tb->drho,&tb->nr,&tb->dr,&tb->cut);
|
||||
}
|
||||
|
||||
MPI_Bcast(&ntypes,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->nrho,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->drho,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->nr,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&tb->dr,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&tb->cut,1,MPI_DOUBLE,0,world);
|
||||
|
||||
// check if ith,jth are consistent with ntypes
|
||||
|
||||
if (ith > ntypes || jth > ntypes)
|
||||
error->all("Requested atom types in EAM setfl file do not exist");
|
||||
|
||||
// allocate potential arrays and read/bcast them
|
||||
// skip sections of file that don't correspond to ith,jth
|
||||
// extract mass, frho for i,i from ith element section
|
||||
// extract rhor for i,j from jth array of ith element section
|
||||
// extract z2r for i,j from ith,jth array of z2r section
|
||||
// note that ith can be < or > than jth
|
||||
// set zr to NULL (funcl array) so it can be deallocated
|
||||
|
||||
tb->frho = new double[tb->nrho+1];
|
||||
tb->rhor = new double[tb->nr+1];
|
||||
tb->z2r = new double[tb->nr+1];
|
||||
tb->zr = NULL;
|
||||
|
||||
int i,j,tmp;
|
||||
double mass;
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
if (me == 0) {
|
||||
fgets(line,MAXLINE,fp);
|
||||
sscanf(line,"%d %lg",&tmp,&mass);
|
||||
}
|
||||
MPI_Bcast(&mass,1,MPI_DOUBLE,0,world);
|
||||
|
||||
if (i == ith && ith == jth) {
|
||||
tb->mass = mass;
|
||||
if (me == 0) grab(fp,tb->nrho,&tb->frho[1]);
|
||||
MPI_Bcast(&tb->frho[1],tb->nrho,MPI_DOUBLE,0,world);
|
||||
|
||||
for (j = 1; j <= ntypes; j++) {
|
||||
if (j == jth) {
|
||||
if (me == 0) grab(fp,tb->nr,&tb->rhor[1]);
|
||||
MPI_Bcast(&tb->rhor[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
} else if (me == 0) skip(fp,tb->nr);
|
||||
}
|
||||
|
||||
} else if (i == ith && ith != jth) {
|
||||
if (me == 0) skip(fp,tb->nrho);
|
||||
for (j = 1; j <= ntypes; j++) {
|
||||
if (j == jth) {
|
||||
if (me == 0) grab(fp,tb->nr,&tb->rhor[1]);
|
||||
MPI_Bcast(&tb->rhor[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
} else if (me == 0) skip(fp,tb->nr);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (me == 0) skip(fp,tb->nrho);
|
||||
if (me == 0) for (j = 1; j <= ntypes; j = j + 1) skip(fp,tb->nr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= ntypes; i++) {
|
||||
for (j = 1; j <= i; j++) {
|
||||
if ((i == ith && j == jth) || (j == ith && i == jth)) {
|
||||
if (me == 0) grab(fp,tb->nr,&tb->z2r[1]);
|
||||
MPI_Bcast(&tb->z2r[1],tb->nr,MPI_DOUBLE,0,world);
|
||||
} else if (me == 0) skip(fp,tb->nr);
|
||||
}
|
||||
}
|
||||
|
||||
// close the potential file
|
||||
|
||||
if (me == 0) fclose(fp);
|
||||
|
||||
ntables++;
|
||||
return ntables-1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
store read-in setfl values in multi-type setfl format
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::store_setfl()
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
// set nrho,nr,drho,dr from any i,i table entry since all the same
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
if (setflag[i][i]) break;
|
||||
|
||||
nrho = tables[tabindex[i][i]].nrho;
|
||||
nr = tables[tabindex[i][i]].nr;
|
||||
drho = tables[tabindex[i][i]].drho;
|
||||
dr = tables[tabindex[i][i]].dr;
|
||||
|
||||
// allocate multi-type setfl arrays
|
||||
|
||||
if (frho) {
|
||||
memory->destroy_2d_double_array(frho);
|
||||
memory->destroy_3d_double_array(rhor_fs);
|
||||
memory->destroy_2d_double_array(zrtmp);
|
||||
memory->destroy_3d_double_array(z2r);
|
||||
}
|
||||
|
||||
frho = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nrho+1,"eam/fs:frho");
|
||||
rhor_fs = (double ***)
|
||||
memory->create_3d_double_array(ntypes+1,ntypes+1,nr+1,"eam/fs:rhor_fs");
|
||||
zrtmp = (double **)
|
||||
memory->create_2d_double_array(ntypes+1,nr+1,"eam/fs:zrtmp");
|
||||
z2r = (double ***)
|
||||
memory->create_3d_double_array(ntypes+1,ntypes+1,nr+1,"eam/fs:frho");
|
||||
|
||||
// copy from read-in tables to multi-type setfl arrays
|
||||
// frho,rhor are 1:ntypes, z2r is 1:ntypes,1:ntypes
|
||||
// skip if setflag i,j = 0 (if hybrid, some may not be set)
|
||||
|
||||
for (i = 1; i <= ntypes; i++)
|
||||
for (j = 1; j <= ntypes; j++) {
|
||||
if (setflag[i][j] == 0) continue;
|
||||
Table *tb = &tables[tabindex[i][j]];
|
||||
if (i == j) for (m = 1; m <= nrho; m++) frho[i][m] = tb->frho[m];
|
||||
for (m = 1; m <= nr; m++) {
|
||||
rhor_fs[i][j][m] = tb->rhor[m];
|
||||
z2r[i][j][m] = tb->z2r[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
interpolate EAM potentials
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::interpolate()
|
||||
{
|
||||
// free memory from previous interpolation
|
||||
|
||||
if (frho_0) interpolate_deallocate();
|
||||
|
||||
// interpolation spacings
|
||||
|
||||
rdr = 1.0/dr;
|
||||
rdrho = 1.0/drho;
|
||||
|
||||
// allocate coeff arrays
|
||||
|
||||
int n = atom->ntypes;
|
||||
|
||||
frho_0 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_0");
|
||||
frho_1 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_1");
|
||||
frho_2 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_2");
|
||||
frho_3 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_3");
|
||||
frho_4 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_4");
|
||||
frho_5 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_5");
|
||||
frho_6 = memory->create_2d_double_array(n+1,nrho+1,"eam/fs:frho_6");
|
||||
|
||||
rhor_fs_0 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_0");
|
||||
rhor_fs_1 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_1");
|
||||
rhor_fs_2 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_2");
|
||||
rhor_fs_3 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_3");
|
||||
rhor_fs_4 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_4");
|
||||
rhor_fs_5 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_5");
|
||||
rhor_fs_6 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:rhor_fs_6");
|
||||
|
||||
z2r_0 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_0");
|
||||
z2r_1 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_1");
|
||||
z2r_2 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_2");
|
||||
z2r_3 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_3");
|
||||
z2r_4 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_4");
|
||||
z2r_5 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_5");
|
||||
z2r_6 = memory->create_3d_double_array(n+1,n+1,nr+1,"eam/fs:z2r_6");
|
||||
|
||||
// frho interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
// if skip, set frho arrays to 0.0, since they will still be accessed
|
||||
// for non-EAM atoms when compute() calculates embedding function
|
||||
|
||||
int i,j,m;
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
if (setflag[i][i] == 0) {
|
||||
for (j = 1; j <= n; j++)
|
||||
for (m = 1; m <= nrho; m++)
|
||||
frho_0[j][m] = frho_1[j][m] = frho_2[j][m] = frho_3[j][m] =
|
||||
frho_4[j][m] = frho_5[j][m] = frho_6[j][m] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nrho; m++) frho_0[i][m] = frho[i][m];
|
||||
|
||||
frho_1[i][1] = frho_0[i][2]-frho_0[i][1];
|
||||
frho_1[i][2] = 0.5*(frho_0[i][3]-frho_0[i][1]);
|
||||
frho_1[i][nrho-1] = 0.5*(frho_0[i][nrho]-frho_0[i][nrho-2]);
|
||||
frho_1[i][nrho] = frho_0[i][nrho]-frho_0[i][nrho-1];
|
||||
|
||||
for (m = 3; m <= nrho-2; m++)
|
||||
frho_1[i][m] = ((frho_0[i][m-2]-frho_0[i][m+2]) +
|
||||
8.0*(frho_0[i][m+1]-frho_0[i][m-1]))/12.0;
|
||||
|
||||
for (m = 1; m <= nrho-1; m++) {
|
||||
frho_2[i][m] = 3.*(frho_0[i][m+1]-frho_0[i][m]) -
|
||||
2.0*frho_1[i][m] - frho_1[i][m+1];
|
||||
frho_3[i][m] = frho_1[i][m] + frho_1[i][m+1] -
|
||||
2.0*(frho_0[i][m+1]-frho_0[i][m]);
|
||||
}
|
||||
|
||||
frho_2[i][nrho] = 0.0;
|
||||
frho_3[i][nrho] = 0.0;
|
||||
|
||||
for (m = 1; m <= nrho; m++) {
|
||||
frho_4[i][m] = frho_1[i][m]/drho;
|
||||
frho_5[i][m] = 2.0*frho_2[i][m]/drho;
|
||||
frho_6[i][m] = 3.0*frho_3[i][m]/drho;
|
||||
}
|
||||
}
|
||||
|
||||
// rhor interpolation for 1:ntypes
|
||||
// skip if setflag = 0 (if hybrid, some may not be set)
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = 1; j <= atom->ntypes; j++) {
|
||||
if (setflag[i][j] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) rhor_fs_0[i][j][m] = rhor_fs[i][j][m];
|
||||
|
||||
rhor_fs_1[i][j][1] = rhor_fs_0[i][j][2]-rhor_fs_0[i][j][1];
|
||||
rhor_fs_1[i][j][2] = 0.5*(rhor_fs_0[i][j][3]-rhor_fs_0[i][j][1]);
|
||||
rhor_fs_1[i][j][nr-1] = 0.5*(rhor_fs_0[i][j][nr]-rhor_fs_0[i][j][nr-2]);
|
||||
rhor_fs_1[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
rhor_fs_1[i][j][m] = ((rhor_fs_0[i][j][m-2]-rhor_fs_0[i][j][m+2]) +
|
||||
8.0*(rhor_fs_0[i][j][m+1]-rhor_fs_0[i][j][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
rhor_fs_2[i][j][m] = 3.0*(rhor_fs_0[i][j][m+1]-rhor_fs_0[i][j][m]) -
|
||||
2.0*rhor_fs_1[i][j][m] - rhor_fs_1[i][j][m+1];
|
||||
rhor_fs_3[i][j][m] = rhor_fs_1[i][j][m] + rhor_fs_1[i][j][m+1] -
|
||||
2.0*(rhor_fs_0[i][j][m+1]-rhor_fs_0[i][j][m]);
|
||||
}
|
||||
|
||||
rhor_fs_2[i][j][nr] = 0.0;
|
||||
rhor_fs_3[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
rhor_fs_4[i][j][m] = rhor_fs_1[i][j][m]/dr;
|
||||
rhor_fs_5[i][j][m] = 2.0*rhor_fs_2[i][j][m]/dr;
|
||||
rhor_fs_6[i][j][m] = 3.0*rhor_fs_3[i][j][m]/dr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// z2r interpolation for 1:ntypes,1:ntypes
|
||||
// skip if setflag i,j = 0 (if hybrid, some may not be set)
|
||||
// set j,i coeffs = i,j coeffs
|
||||
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (setflag[i][j] == 0) continue;
|
||||
|
||||
for (m = 1; m <= nr; m++) z2r_0[i][j][m] = z2r[i][j][m];
|
||||
|
||||
z2r_1[i][j][1] = z2r_0[i][j][2]-z2r_0[i][j][1];
|
||||
z2r_1[i][j][2] = 0.5*(z2r_0[i][j][3]-z2r_0[i][j][1]);
|
||||
z2r_1[i][j][nr-1] = 0.5*(z2r_0[i][j][nr]-z2r_0[i][j][nr-2]);
|
||||
z2r_1[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 3; m <= nr-2; m++)
|
||||
z2r_1[i][j][m] = ((z2r_0[i][j][m-2]-z2r_0[i][j][m+2]) +
|
||||
8.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m-1]))/12.;
|
||||
|
||||
for (m = 1; m <= nr-1; m++) {
|
||||
z2r_2[i][j][m] = 3.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]) -
|
||||
2.0*z2r_1[i][j][m] - z2r_1[i][j][m+1];
|
||||
z2r_3[i][j][m] = z2r_1[i][j][m] + z2r_1[i][j][m+1] -
|
||||
2.0*(z2r_0[i][j][m+1]-z2r_0[i][j][m]);
|
||||
}
|
||||
|
||||
z2r_2[i][j][nr] = 0.0;
|
||||
z2r_3[i][j][nr] = 0.0;
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_4[i][j][m] = z2r_1[i][j][m]/dr;
|
||||
z2r_5[i][j][m] = 2.0*z2r_2[i][j][m]/dr;
|
||||
z2r_6[i][j][m] = 3.0*z2r_3[i][j][m]/dr;
|
||||
}
|
||||
|
||||
for (m = 1; m <= nr; m++) {
|
||||
z2r_0[j][i][m] = z2r_0[i][j][m];
|
||||
z2r_1[j][i][m] = z2r_1[i][j][m];
|
||||
z2r_2[j][i][m] = z2r_2[i][j][m];
|
||||
z2r_3[j][i][m] = z2r_3[i][j][m];
|
||||
z2r_4[j][i][m] = z2r_4[i][j][m];
|
||||
z2r_5[j][i][m] = z2r_5[i][j][m];
|
||||
z2r_6[j][i][m] = z2r_6[i][j][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
deallocate spline interpolation arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::interpolate_deallocate()
|
||||
{
|
||||
memory->destroy_2d_double_array(frho_0);
|
||||
memory->destroy_2d_double_array(frho_1);
|
||||
memory->destroy_2d_double_array(frho_2);
|
||||
memory->destroy_2d_double_array(frho_3);
|
||||
memory->destroy_2d_double_array(frho_4);
|
||||
memory->destroy_2d_double_array(frho_5);
|
||||
memory->destroy_2d_double_array(frho_6);
|
||||
|
||||
memory->destroy_3d_double_array(rhor_fs_0);
|
||||
memory->destroy_3d_double_array(rhor_fs_1);
|
||||
memory->destroy_3d_double_array(rhor_fs_2);
|
||||
memory->destroy_3d_double_array(rhor_fs_3);
|
||||
memory->destroy_3d_double_array(rhor_fs_4);
|
||||
memory->destroy_3d_double_array(rhor_fs_5);
|
||||
memory->destroy_3d_double_array(rhor_fs_6);
|
||||
|
||||
memory->destroy_3d_double_array(z2r_0);
|
||||
memory->destroy_3d_double_array(z2r_1);
|
||||
memory->destroy_3d_double_array(z2r_2);
|
||||
memory->destroy_3d_double_array(z2r_3);
|
||||
memory->destroy_3d_double_array(z2r_4);
|
||||
memory->destroy_3d_double_array(z2r_5);
|
||||
memory->destroy_3d_double_array(z2r_6);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairEAMFS::single(int i, int j, int itype, int jtype,
|
||||
double rsq, double factor_coul, double factor_lj,
|
||||
int eflag, One &one)
|
||||
{
|
||||
double r,p,rhoip,rhojp,z2,z2p,recip,phi,phip,psip;
|
||||
int m;
|
||||
|
||||
r = sqrt(rsq);
|
||||
p = r*rdr + 1.0;
|
||||
m = static_cast<int> (p);
|
||||
m = MIN(m,nr-1);
|
||||
p -= m;
|
||||
p = MIN(p,1.0);
|
||||
|
||||
rhoip = (rhor_fs_6[itype][jtype][m]*p + rhor_fs_5[itype][jtype][m])*p +
|
||||
rhor_fs_4[itype][jtype][m];
|
||||
rhojp = (rhor_fs_6[jtype][itype][m]*p + rhor_fs_5[jtype][itype][m])*p +
|
||||
rhor_fs_4[jtype][itype][m];
|
||||
z2 = ((z2r_3[itype][jtype][m]*p + z2r_2[itype][jtype][m])*p +
|
||||
z2r_1[itype][jtype][m])*p + z2r_0[itype][jtype][m];
|
||||
z2p = (z2r_6[itype][jtype][m]*p + z2r_5[itype][jtype][m])*p +
|
||||
z2r_4[itype][jtype][m];
|
||||
|
||||
recip = 1.0/r;
|
||||
phi = z2*recip;
|
||||
phip = z2p*recip - phi*recip;
|
||||
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
|
||||
one.fforce = -psip*recip;
|
||||
|
||||
if (eflag) {
|
||||
one.eng_vdwl = phi;
|
||||
one.eng_coul = 0.0;
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_EAM_FS_H
|
||||
#define PAIR_EAM_FS_H
|
||||
|
||||
#include "pair_eam.h"
|
||||
|
||||
class PairEAMFS : public PairEAM {
|
||||
public:
|
||||
PairEAMFS();
|
||||
~PairEAMFS();
|
||||
void compute(int, int);
|
||||
void coeff(int, char **);
|
||||
double init_one(int, int);
|
||||
void init_style();
|
||||
void single(int, int, int, int, double, double, double, int, One &);
|
||||
|
||||
private:
|
||||
double ***rhor_fs;
|
||||
double ***rhor_fs_0,***rhor_fs_1,***rhor_fs_2,***rhor_fs_3;
|
||||
double ***rhor_fs_4,***rhor_fs_5,***rhor_fs_6;
|
||||
|
||||
int read_setfl(char *, int, int);
|
||||
void store_setfl();
|
||||
void interpolate();
|
||||
void interpolate_deallocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,493 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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: Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "pair_lj_charmm_coul_charmm.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLJCharmmCoulCharmm::~PairLJCharmmCoulCharmm()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->destroy_2d_int_array(setflag);
|
||||
memory->destroy_2d_double_array(cutsq);
|
||||
|
||||
memory->destroy_2d_double_array(epsilon);
|
||||
memory->destroy_2d_double_array(sigma);
|
||||
memory->destroy_2d_double_array(eps14);
|
||||
memory->destroy_2d_double_array(sigma14);
|
||||
memory->destroy_2d_double_array(lj1);
|
||||
memory->destroy_2d_double_array(lj2);
|
||||
memory->destroy_2d_double_array(lj3);
|
||||
memory->destroy_2d_double_array(lj4);
|
||||
memory->destroy_2d_double_array(lj14_1);
|
||||
memory->destroy_2d_double_array(lj14_2);
|
||||
memory->destroy_2d_double_array(lj14_3);
|
||||
memory->destroy_2d_double_array(lj14_4);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,numneigh,itype,jtype;
|
||||
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
|
||||
double rsq,r2inv,r6inv,forcecoul,forcelj,fforce,factor_coul,factor_lj;
|
||||
double factor,phicoul,philj,switch1,switch2;
|
||||
int *neighs;
|
||||
double **f;
|
||||
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) f = update->f_pair;
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
double *q = atom->q;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
double *special_coul = force->special_coul;
|
||||
double *special_lj = force->special_lj;
|
||||
int newton_pair = force->newton_pair;
|
||||
double qqrd2e = force->qqrd2e;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
qtmp = q[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
if (j < nall) factor_coul = factor_lj = 1.0;
|
||||
else {
|
||||
factor_coul = special_coul[j/nall];
|
||||
factor_lj = special_lj[j/nall];
|
||||
j %= nall;
|
||||
}
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cut_bothsq) {
|
||||
r2inv = 1.0/rsq;
|
||||
|
||||
if (rsq < cut_coulsq) {
|
||||
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
|
||||
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
|
||||
(rsq-cut_coul_innersq) / denom_coul;
|
||||
forcecoul *= switch1 + switch2;
|
||||
}
|
||||
} else forcecoul = 0.0;
|
||||
|
||||
if (rsq < cut_ljsq) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
jtype = type[j];
|
||||
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
|
||||
(rsq-cut_lj_innersq) / denom_lj;
|
||||
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
|
||||
forcelj = forcelj*switch1 + philj*switch2;
|
||||
}
|
||||
} else forcelj = 0.0;
|
||||
|
||||
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
|
||||
|
||||
f[i][0] += delx*fforce;
|
||||
f[i][1] += dely*fforce;
|
||||
f[i][2] += delz*fforce;
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] -= delx*fforce;
|
||||
f[j][1] -= dely*fforce;
|
||||
f[j][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (newton_pair || j < nlocal) factor = 1.0;
|
||||
else factor = 0.5;
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
|
||||
denom_coul;
|
||||
phicoul *= switch1;
|
||||
}
|
||||
eng_coul += factor*factor_coul*phicoul;
|
||||
}
|
||||
if (rsq < cut_ljsq) {
|
||||
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
philj *= switch1;
|
||||
}
|
||||
eng_vdwl += factor*factor_lj*philj;
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag == 1) {
|
||||
if (newton_pair || j < nlocal) {
|
||||
virial[0] += delx*delx*fforce;
|
||||
virial[1] += dely*dely*fforce;
|
||||
virial[2] += delz*delz*fforce;
|
||||
virial[3] += delx*dely*fforce;
|
||||
virial[4] += delx*delz*fforce;
|
||||
virial[5] += dely*delz*fforce;
|
||||
} else {
|
||||
virial[0] += 0.5*delx*delx*fforce;
|
||||
virial[1] += 0.5*dely*dely*fforce;
|
||||
virial[2] += 0.5*delz*delz*fforce;
|
||||
virial[3] += 0.5*delx*dely*fforce;
|
||||
virial[4] += 0.5*delx*delz*fforce;
|
||||
virial[5] += 0.5*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) virial_compute();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
|
||||
|
||||
epsilon = memory->create_2d_double_array(n+1,n+1,"pair:epsilon");
|
||||
sigma = memory->create_2d_double_array(n+1,n+1,"pair:sigma");
|
||||
eps14 = memory->create_2d_double_array(n+1,n+1,"pair:eps14");
|
||||
sigma14 = memory->create_2d_double_array(n+1,n+1,"pair:sigma14");
|
||||
lj1 = memory->create_2d_double_array(n+1,n+1,"pair:lj1");
|
||||
lj2 = memory->create_2d_double_array(n+1,n+1,"pair:lj2");
|
||||
lj3 = memory->create_2d_double_array(n+1,n+1,"pair:lj3");
|
||||
lj4 = memory->create_2d_double_array(n+1,n+1,"pair:lj4");
|
||||
lj14_1 = memory->create_2d_double_array(n+1,n+1,"pair:lj14_1");
|
||||
lj14_2 = memory->create_2d_double_array(n+1,n+1,"pair:lj14_2");
|
||||
lj14_3 = memory->create_2d_double_array(n+1,n+1,"pair:lj14_3");
|
||||
lj14_4 = memory->create_2d_double_array(n+1,n+1,"pair:lj14_4");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
unlike other pair styles,
|
||||
there are no individual pair settings that these override
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg != 2 && narg != 4)
|
||||
error->all("Illegal pair_style command");
|
||||
|
||||
cut_lj_inner = atof(arg[0]);
|
||||
cut_lj = atof(arg[1]);
|
||||
if (narg == 2) {
|
||||
cut_coul_inner = cut_lj_inner;
|
||||
cut_coul = cut_lj;
|
||||
} else {
|
||||
cut_coul_inner = atof(arg[2]);
|
||||
cut_coul = atof(arg[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg != 4 && narg != 6)
|
||||
error->all("Incorrect args for pair coefficients");
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double epsilon_one = atof(arg[2]);
|
||||
double sigma_one = atof(arg[3]);
|
||||
double eps14_one = epsilon_one;
|
||||
double sigma14_one = sigma_one;
|
||||
if (narg == 6) {
|
||||
eps14_one = atof(arg[4]);
|
||||
sigma14_one = atof(arg[5]);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
epsilon[i][j] = epsilon_one;
|
||||
sigma[i][j] = sigma_one;
|
||||
eps14[i][j] = eps14_one;
|
||||
sigma14[i][j] = sigma14_one;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all("Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairLJCharmmCoulCharmm::init_one(int i, int j)
|
||||
{
|
||||
// always mix arithmetically
|
||||
|
||||
if (setflag[i][j] == 0) {
|
||||
epsilon[i][j] = sqrt(epsilon[i][i]*epsilon[j][j]);
|
||||
sigma[i][j] = 0.5 * (sigma[i][i] + sigma[j][j]);
|
||||
eps14[i][j] = sqrt(eps14[i][i]*eps14[j][j]);
|
||||
sigma14[i][j] = 0.5 * (sigma14[i][i] + sigma14[j][j]);
|
||||
}
|
||||
|
||||
double cut = MAX(cut_lj,cut_coul);
|
||||
|
||||
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
|
||||
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
|
||||
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
|
||||
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
|
||||
lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
|
||||
lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
|
||||
lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
|
||||
lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
|
||||
|
||||
lj1[j][i] = lj1[i][j];
|
||||
lj2[j][i] = lj2[i][j];
|
||||
lj3[j][i] = lj3[i][j];
|
||||
lj4[j][i] = lj4[i][j];
|
||||
lj14_1[j][i] = lj14_1[i][j];
|
||||
lj14_2[j][i] = lj14_2[i][j];
|
||||
lj14_3[j][i] = lj14_3[i][j];
|
||||
lj14_4[j][i] = lj14_4[i][j];
|
||||
|
||||
return cut;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::init_style()
|
||||
{
|
||||
// require an atom style with charge defined
|
||||
|
||||
if (atom->charge_allow == 0)
|
||||
error->all("Must use charged atom style with this pair style");
|
||||
|
||||
// require cut_lj_inner < cut_lj, cut_coul_inner < cut_coul
|
||||
|
||||
if (cut_lj_inner >= cut_lj || cut_coul_inner >= cut_coul)
|
||||
error->all("Pair inner cutoff >= Pair outer cutoff");
|
||||
|
||||
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
|
||||
cut_ljsq = cut_lj * cut_lj;
|
||||
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
|
||||
cut_coulsq = cut_coul * cut_coul;
|
||||
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
|
||||
|
||||
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
|
||||
(cut_ljsq-cut_lj_innersq);
|
||||
denom_coul = (cut_coulsq-cut_coul_innersq) * (cut_coulsq-cut_coul_innersq) *
|
||||
(cut_coulsq-cut_coul_innersq);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::write_restart(FILE *fp)
|
||||
{
|
||||
write_restart_settings(fp);
|
||||
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
fwrite(&setflag[i][j],sizeof(int),1,fp);
|
||||
if (setflag[i][j]) {
|
||||
fwrite(&epsilon[i][j],sizeof(double),1,fp);
|
||||
fwrite(&sigma[i][j],sizeof(double),1,fp);
|
||||
fwrite(&eps14[i][j],sizeof(double),1,fp);
|
||||
fwrite(&sigma14[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::read_restart(FILE *fp)
|
||||
{
|
||||
read_restart_settings(fp);
|
||||
|
||||
allocate();
|
||||
|
||||
int i,j;
|
||||
int me = comm->me;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
|
||||
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
|
||||
if (setflag[i][j]) {
|
||||
if (me == 0) {
|
||||
fread(&epsilon[i][j],sizeof(double),1,fp);
|
||||
fread(&sigma[i][j],sizeof(double),1,fp);
|
||||
fread(&eps14[i][j],sizeof(double),1,fp);
|
||||
fread(&sigma14[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::write_restart_settings(FILE *fp)
|
||||
{
|
||||
fwrite(&cut_lj_inner,sizeof(double),1,fp);
|
||||
fwrite(&cut_lj,sizeof(double),1,fp);
|
||||
fwrite(&cut_coul_inner,sizeof(double),1,fp);
|
||||
fwrite(&cut_coul,sizeof(double),1,fp);
|
||||
fwrite(&offset_flag,sizeof(int),1,fp);
|
||||
fwrite(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::read_restart_settings(FILE *fp)
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
fread(&cut_lj_inner,sizeof(double),1,fp);
|
||||
fread(&cut_lj,sizeof(double),1,fp);
|
||||
fread(&cut_coul_inner,sizeof(double),1,fp);
|
||||
fread(&cut_coul,sizeof(double),1,fp);
|
||||
fread(&offset_flag,sizeof(int),1,fp);
|
||||
fread(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_coul_inner,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmm::single(int i, int j, int itype, int jtype,
|
||||
double rsq, double factor_coul,
|
||||
double factor_lj,
|
||||
int eflag, One &one)
|
||||
{
|
||||
double r2inv,r6inv,switch1,switch2,forcecoul,forcelj,phicoul,philj;
|
||||
|
||||
r2inv = 1.0/rsq;
|
||||
if (rsq < cut_coulsq) {
|
||||
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
|
||||
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
|
||||
(rsq-cut_coul_innersq) / denom_coul;
|
||||
forcecoul *= switch1 + switch2;
|
||||
}
|
||||
} else forcecoul = 0.0;
|
||||
if (rsq < cut_ljsq) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
|
||||
(rsq-cut_lj_innersq) / denom_lj;
|
||||
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
|
||||
forcelj = forcelj*switch1 + philj*switch2;
|
||||
}
|
||||
} else forcelj = 0.0;
|
||||
one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
|
||||
|
||||
if (eflag) {
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
|
||||
denom_coul;
|
||||
phicoul *= switch1;
|
||||
}
|
||||
one.eng_coul = factor_coul*phicoul;
|
||||
} else one.eng_coul = 0.0;
|
||||
if (rsq < cut_ljsq) {
|
||||
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
philj *= switch1;
|
||||
}
|
||||
one.eng_vdwl = factor_lj*philj;
|
||||
} else one.eng_vdwl = 0.0;
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_LJ_CHARMM_COUL_CHARMM_H
|
||||
#define PAIR_LJ_CHARMM_COUL_CHARMM_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
class PairLJCharmmCoulCharmm : public Pair {
|
||||
public:
|
||||
// these variables are public so DihedralCharmm can see them
|
||||
double **lj14_1,**lj14_2,**lj14_3,**lj14_4;
|
||||
|
||||
PairLJCharmmCoulCharmm() {}
|
||||
~PairLJCharmmCoulCharmm();
|
||||
virtual void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, char **);
|
||||
double init_one(int, int);
|
||||
void init_style();
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void write_restart_settings(FILE *);
|
||||
void read_restart_settings(FILE *);
|
||||
virtual void single(int, int, int, int, double, double, double, int, One &);
|
||||
|
||||
protected:
|
||||
double cut_lj_inner,cut_lj,cut_coul_inner,cut_coul;
|
||||
double cut_lj_innersq,cut_ljsq,cut_coul_innersq,cut_coulsq,cut_bothsq;
|
||||
double denom_lj,denom_coul;
|
||||
double **epsilon,**sigma,**eps14,**sigma14;
|
||||
double **lj1,**lj2,**lj3,**lj4;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,214 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "pair_lj_charmm_coul_charmm_implicit.h"
|
||||
#include "atom.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "neighbor.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmmImplicit::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,numneigh,itype,jtype;
|
||||
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
|
||||
double rsq,r2inv,r6inv,forcecoul,forcelj,fforce,factor_coul,factor_lj;
|
||||
double factor,phicoul,philj,switch1,switch2;
|
||||
int *neighs;
|
||||
double **f;
|
||||
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) f = update->f_pair;
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
double *q = atom->q;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
double *special_coul = force->special_coul;
|
||||
double *special_lj = force->special_lj;
|
||||
int newton_pair = force->newton_pair;
|
||||
double qqrd2e = force->qqrd2e;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
qtmp = q[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
if (j < nall) factor_coul = factor_lj = 1.0;
|
||||
else {
|
||||
factor_coul = special_coul[j/nall];
|
||||
factor_lj = special_lj[j/nall];
|
||||
j %= nall;
|
||||
}
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq < cut_bothsq) {
|
||||
r2inv = 1.0/rsq;
|
||||
|
||||
if (rsq < cut_coulsq) {
|
||||
forcecoul = 2.0 * qqrd2e * qtmp*q[j]*r2inv;
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
|
||||
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
|
||||
(rsq-cut_coul_innersq) / denom_coul;
|
||||
forcecoul *= switch1 + switch2;
|
||||
}
|
||||
} else forcecoul = 0.0;
|
||||
|
||||
if (rsq < cut_ljsq) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
jtype = type[j];
|
||||
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
|
||||
(rsq-cut_lj_innersq) / denom_lj;
|
||||
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
|
||||
forcelj = forcelj*switch1 + philj*switch2;
|
||||
}
|
||||
} else forcelj = 0.0;
|
||||
|
||||
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
|
||||
|
||||
f[i][0] += delx*fforce;
|
||||
f[i][1] += dely*fforce;
|
||||
f[i][2] += delz*fforce;
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] -= delx*fforce;
|
||||
f[j][1] -= dely*fforce;
|
||||
f[j][2] -= delz*fforce;
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (newton_pair || j < nlocal) factor = 1.0;
|
||||
else factor = 0.5;
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = qqrd2e * qtmp*q[j]*r2inv;
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
|
||||
denom_coul;
|
||||
phicoul *= switch1;
|
||||
}
|
||||
eng_coul += factor*factor_coul*phicoul;
|
||||
}
|
||||
if (rsq < cut_ljsq) {
|
||||
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
philj *= switch1;
|
||||
}
|
||||
eng_vdwl += factor*factor_lj*philj;
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag == 1) {
|
||||
if (newton_pair || j < nlocal) {
|
||||
virial[0] += delx*delx*fforce;
|
||||
virial[1] += dely*dely*fforce;
|
||||
virial[2] += delz*delz*fforce;
|
||||
virial[3] += delx*dely*fforce;
|
||||
virial[4] += delx*delz*fforce;
|
||||
virial[5] += dely*delz*fforce;
|
||||
} else {
|
||||
virial[0] += 0.5*delx*delx*fforce;
|
||||
virial[1] += 0.5*dely*dely*fforce;
|
||||
virial[2] += 0.5*delz*delz*fforce;
|
||||
virial[3] += 0.5*delx*dely*fforce;
|
||||
virial[4] += 0.5*delx*delz*fforce;
|
||||
virial[5] += 0.5*dely*delz*fforce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) virial_compute();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCharmmCoulCharmmImplicit::single(int i, int j, int itype, int jtype,
|
||||
double rsq, double factor_coul,
|
||||
double factor_lj,
|
||||
int eflag, One &one)
|
||||
{
|
||||
double r2inv,r6inv,switch1,switch2,forcecoul,forcelj,phicoul,philj;
|
||||
|
||||
r2inv = 1.0/rsq;
|
||||
if (rsq < cut_coulsq) {
|
||||
forcecoul = 2.0 * force->qqrd2e * atom->q[i]*atom->q[j]*r2inv;
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
|
||||
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
|
||||
(rsq-cut_coul_innersq) / denom_coul;
|
||||
forcecoul *= switch1 + switch2;
|
||||
}
|
||||
} else forcecoul = 0.0;
|
||||
if (rsq < cut_ljsq) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
|
||||
(rsq-cut_lj_innersq) / denom_lj;
|
||||
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
|
||||
forcelj = forcelj*switch1 + philj*switch2;
|
||||
}
|
||||
} else forcelj = 0.0;
|
||||
one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
|
||||
|
||||
if (eflag) {
|
||||
if (rsq < cut_coulsq) {
|
||||
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*r2inv;
|
||||
if (rsq > cut_coul_innersq) {
|
||||
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
|
||||
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
|
||||
denom_coul;
|
||||
phicoul *= switch1;
|
||||
}
|
||||
one.eng_coul = factor_coul*phicoul;
|
||||
} else one.eng_coul = 0.0;
|
||||
if (rsq < cut_ljsq) {
|
||||
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
|
||||
if (rsq > cut_lj_innersq) {
|
||||
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
|
||||
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
|
||||
philj *= switch1;
|
||||
}
|
||||
one.eng_vdwl = factor_lj*philj;
|
||||
} else one.eng_vdwl = 0.0;
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_LJ_CHARMM_COUL_CHARMM_IMPLICIT_H
|
||||
#define PAIR_LJ_CHARMM_COUL_CHARMM_IMPLICIT_H
|
||||
|
||||
#include "pair_lj_charmm_coul_charmm.h"
|
||||
|
||||
class PairLJCharmmCoulCharmmImplicit : public PairLJCharmmCoulCharmm {
|
||||
public:
|
||||
void compute(int, int);
|
||||
void single(int, int, int, int, double, double, double, int, One &);
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,59 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_LJ_CUT_COUL_LONG_H
|
||||
#define PAIR_LJ_CUT_COUL_LONG_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
class PairLJCutCoulLong : public Pair {
|
||||
public:
|
||||
double cut_coul;
|
||||
|
||||
PairLJCutCoulLong();
|
||||
~PairLJCutCoulLong();
|
||||
virtual void compute(int, int);
|
||||
virtual void settings(int, char **);
|
||||
void coeff(int, char **);
|
||||
double init_one(int, int);
|
||||
virtual void init_style();
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
virtual void write_restart_settings(FILE *);
|
||||
virtual void read_restart_settings(FILE *);
|
||||
virtual void single(int, int, int, int, double, double, double, int, One &);
|
||||
|
||||
void compute_inner();
|
||||
void compute_middle();
|
||||
void compute_outer(int, int);
|
||||
|
||||
protected:
|
||||
double cut_lj_global;
|
||||
double **cut_lj,**cut_ljsq;
|
||||
double cut_coulsq;
|
||||
double **epsilon,**sigma;
|
||||
double **lj1,**lj2,**lj3,**lj4,**offset;
|
||||
double *cut_respa;
|
||||
double g_ewald;
|
||||
|
||||
double tabinnersq;
|
||||
double *rtable,*drtable,*ftable,*dftable,*ctable,*dctable;
|
||||
double *etable,*detable,*ptable,*dptable,*vtable,*dvtable;
|
||||
int ncoulshiftbits,ncoulmask;
|
||||
|
||||
void allocate();
|
||||
void init_tables();
|
||||
void free_tables();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,528 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Amalie Frischknecht and Ahmed Ismail (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "pair_lj_cut_coul_long_tip4p.h"
|
||||
#include "angle.h"
|
||||
#include "atom.h"
|
||||
#include "bond.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "kspace.h"
|
||||
#include "update.h"
|
||||
#include "respa.h"
|
||||
#include "memory.h"
|
||||
#include "neighbor.h"
|
||||
#include "error.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define EWALD_F 1.12837917
|
||||
#define EWALD_P 0.3275911
|
||||
#define A1 0.254829592
|
||||
#define A2 -0.284496736
|
||||
#define A3 1.421413741
|
||||
#define A4 -1.453152027
|
||||
#define A5 1.061405429
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairLJCutCoulLongTIP4P::PairLJCutCoulLongTIP4P()
|
||||
{
|
||||
single_enable = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,k,numneigh,itype,jtype,itable;
|
||||
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fraction,table;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,delx3,dely3,delz3;
|
||||
double r,r2inv,r6inv,forcecoul,forcelj,cforce,negforce;
|
||||
double factor_coul,factor_lj;
|
||||
double grij,expm2,prefactor,t,erfc;
|
||||
double phicoul,philj;
|
||||
int iH1,iH2,jH1,jH2;
|
||||
double xiM[3],xjM[3];
|
||||
double *x1,*x2;
|
||||
double fO[3],fH[3];
|
||||
int *neighs;
|
||||
double **f;
|
||||
float rsq;
|
||||
int *int_rsq = (int *) &rsq;
|
||||
|
||||
eng_vdwl = eng_coul = 0.0;
|
||||
if (vflag) for (i = 0; i < 6; i++) virial[i] = tvirial[i] = 0.0;
|
||||
|
||||
if (vflag == 2) {
|
||||
f = update->f_pair;
|
||||
tf = atom->f;
|
||||
}
|
||||
else f = atom->f;
|
||||
double **x = atom->x;
|
||||
double *q = atom->q;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
double *special_coul = force->special_coul;
|
||||
double *special_lj = force->special_lj;
|
||||
double qqrd2e = force->qqrd2e;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
qtmp = q[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
if (itype == typeO) {
|
||||
find_M(i,iH1,iH2,xiM);
|
||||
x1 = xiM;
|
||||
} else x1 = x[i];
|
||||
neighs = neighbor->firstneigh[i];
|
||||
numneigh = neighbor->numneigh[i];
|
||||
|
||||
for (k = 0; k < numneigh; k++) {
|
||||
j = neighs[k];
|
||||
|
||||
if (j < nall) factor_coul = factor_lj = 1.0;
|
||||
else {
|
||||
factor_coul = special_coul[j/nall];
|
||||
factor_lj = special_lj[j/nall];
|
||||
j %= nall;
|
||||
}
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
jtype = type[j];
|
||||
|
||||
if (rsq < cutsq[itype][jtype]) {
|
||||
|
||||
r2inv = 1.0/rsq;
|
||||
|
||||
if (rsq < cut_ljsq[itype][jtype]) {
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
|
||||
forcelj *= factor_lj * r2inv;
|
||||
|
||||
f[i][0] += delx*forcelj;
|
||||
f[i][1] += dely*forcelj;
|
||||
f[i][2] += delz*forcelj;
|
||||
f[j][0] -= delx*forcelj;
|
||||
f[j][1] -= dely*forcelj;
|
||||
f[j][2] -= delz*forcelj;
|
||||
|
||||
if (eflag) {
|
||||
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
|
||||
offset[itype][jtype];
|
||||
eng_vdwl += factor_lj*philj;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust rsq for off-site O charge(s)
|
||||
|
||||
if (itype == typeO || jtype == typeO) {
|
||||
if (jtype == typeO) {
|
||||
find_M(j,jH1,jH2,xjM);
|
||||
x2 = xjM;
|
||||
} else x2 = x[j];
|
||||
delx = x1[0] - x2[0];
|
||||
dely = x1[1] - x2[1];
|
||||
delz = x1[2] - x2[2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
}
|
||||
|
||||
// test current rsq against cutoff and compute Coulombic force
|
||||
|
||||
if (rsq < cut_coulsq) {
|
||||
if (!ncoultablebits || rsq <= tabinnersq) {
|
||||
r = sqrtf(rsq);
|
||||
r2inv = 1 / rsq;
|
||||
grij = g_ewald * r;
|
||||
expm2 = exp(-grij*grij);
|
||||
t = 1.0 / (1.0 + EWALD_P*grij);
|
||||
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
|
||||
prefactor = qqrd2e * qtmp*q[j]/r;
|
||||
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
|
||||
if (factor_coul < 1.0) {
|
||||
forcecoul -= (1.0-factor_coul)*prefactor;
|
||||
}
|
||||
} else {
|
||||
r2inv = 1 / rsq;
|
||||
itable = *int_rsq & ncoulmask;
|
||||
itable >>= ncoulshiftbits;
|
||||
fraction = (rsq - rtable[itable]) * drtable[itable];
|
||||
table = ftable[itable] + fraction*dftable[itable];
|
||||
forcecoul = qtmp*q[j] * table;
|
||||
if (factor_coul < 1.0) {
|
||||
table = ctable[itable] + fraction*dctable[itable];
|
||||
prefactor = qtmp*q[j] * table;
|
||||
forcecoul -= (1.0-factor_coul)*prefactor;
|
||||
}
|
||||
}
|
||||
|
||||
cforce = forcecoul * r2inv;
|
||||
|
||||
// if i,j are not O atoms, force is applied directly
|
||||
// if i or j are O atoms, force is on fictitious atoms
|
||||
// spread force to all 3 atoms in water molecule
|
||||
// formulas due to Feenstra et al, J Comp Chem, 20, 786 (1999)
|
||||
|
||||
if (itype != typeO) {
|
||||
if (vflag == 0) {
|
||||
f[i][0] += delx * cforce;
|
||||
f[i][1] += dely * cforce;
|
||||
f[i][2] += delz * cforce;
|
||||
} else {
|
||||
tf[i][0] += delx * cforce;
|
||||
tf[i][1] += dely * cforce;
|
||||
tf[i][2] += delz * cforce;
|
||||
|
||||
tvirial[0] += 0.5 * delx * delx * cforce;
|
||||
tvirial[1] += 0.5 * dely * dely * cforce;
|
||||
tvirial[2] += 0.5 * delz * delz * cforce;
|
||||
tvirial[3] += 0.5 * dely * delx * cforce;
|
||||
tvirial[4] += 0.5 * delz * delx * cforce;
|
||||
tvirial[5] += 0.5 * delz * dely * cforce;
|
||||
}
|
||||
|
||||
} else {
|
||||
fO[0] = delx*cforce*(1.0-2.0*alpha);
|
||||
fO[1] = dely*cforce*(1.0-2.0*alpha);
|
||||
fO[2] = delz*cforce*(1.0-2.0*alpha);
|
||||
|
||||
fH[0] = alpha * (delx*cforce);
|
||||
fH[1] = alpha * (dely*cforce);
|
||||
fH[2] = alpha * (delz*cforce);
|
||||
|
||||
if (vflag == 0) {
|
||||
f[i][0] += fO[0];
|
||||
f[i][1] += fO[1];
|
||||
f[i][2] += fO[2];
|
||||
|
||||
f[iH1][0] += fH[0];
|
||||
f[iH1][1] += fH[1];
|
||||
f[iH1][2] += fH[2];
|
||||
|
||||
f[iH2][0] += fH[0];
|
||||
f[iH2][1] += fH[1];
|
||||
f[iH2][2] += fH[2];
|
||||
|
||||
} else {
|
||||
tf[i][0] += fO[0];
|
||||
tf[i][1] += fO[1];
|
||||
tf[i][2] += fO[2];
|
||||
|
||||
tf[iH1][0] += fH[0];
|
||||
tf[iH1][1] += fH[1];
|
||||
tf[iH1][2] += fH[2];
|
||||
|
||||
tf[iH2][0] += fH[0];
|
||||
tf[iH2][1] += fH[1];
|
||||
tf[iH2][2] += fH[2];
|
||||
|
||||
delx1 = x[i][0] - x2[0];
|
||||
dely1 = x[i][1] - x2[1];
|
||||
delz1 = x[i][2] - x2[2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
delx2 = x[iH1][0] - x2[0];
|
||||
dely2 = x[iH1][1] - x2[1];
|
||||
delz2 = x[iH1][2] - x2[2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
delx3 = x[iH2][0] - x2[0];
|
||||
dely3 = x[iH2][1] - x2[1];
|
||||
delz3 = x[iH2][2] - x2[2];
|
||||
domain->minimum_image(&delx3,&dely3,&delz3);
|
||||
|
||||
tvirial[0] += 0.5 * (delx1 * fO[0] + (delx2 + delx3) * fH[0]);
|
||||
tvirial[1] += 0.5 * (dely1 * fO[1] + (dely2 + dely3) * fH[1]);
|
||||
tvirial[2] += 0.5 * (delz1 * fO[2] + (delz2 + delz3) * fH[2]);
|
||||
tvirial[3] += 0.5 * (dely1 * fO[0] + (dely2 + dely3) * fH[0]);
|
||||
tvirial[4] += 0.5 * (delz1 * fO[0] + (delz2 + delz3) * fH[0]);
|
||||
tvirial[5] += 0.5 * (delz1 * fO[1] + (delz2 + delz3) * fH[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (jtype != typeO) {
|
||||
if (vflag == 0) {
|
||||
f[j][0] -= delx * cforce;
|
||||
f[j][1] -= dely * cforce;
|
||||
f[j][2] -= delz * cforce;
|
||||
} else {
|
||||
tf[j][0] -= delx * cforce;
|
||||
tf[j][1] -= dely * cforce;
|
||||
tf[j][2] -= delz * cforce;
|
||||
|
||||
tvirial[0] += 0.5 * (delx * delx * cforce);
|
||||
tvirial[1] += 0.5 * (dely * dely * cforce);
|
||||
tvirial[2] += 0.5 * (delz * delz * cforce);
|
||||
tvirial[3] += 0.5 * (dely * delx * cforce);
|
||||
tvirial[4] += 0.5 * (delz * delx * cforce);
|
||||
tvirial[5] += 0.5 * (delz * dely * cforce);
|
||||
}
|
||||
|
||||
} else {
|
||||
negforce = -cforce;
|
||||
|
||||
fO[0] = delx*negforce*(1.0-2.0*alpha);
|
||||
fO[1] = dely*negforce*(1.0-2.0*alpha);
|
||||
fO[2] = delz*negforce*(1.0-2.0*alpha);
|
||||
|
||||
fH[0] = alpha * (delx*negforce);
|
||||
fH[1] = alpha * (dely*negforce);
|
||||
fH[2] = alpha * (delz*negforce);
|
||||
|
||||
if (vflag != 2) {
|
||||
f[j][0] += fO[0];
|
||||
f[j][1] += fO[1];
|
||||
f[j][2] += fO[2];
|
||||
|
||||
f[jH1][0] += fH[0];
|
||||
f[jH1][1] += fH[1];
|
||||
f[jH1][2] += fH[2];
|
||||
|
||||
f[jH2][0] += fH[0];
|
||||
f[jH2][1] += fH[1];
|
||||
f[jH2][2] += fH[2];
|
||||
|
||||
} else {
|
||||
tf[j][0] += fO[0];
|
||||
tf[j][1] += fO[1];
|
||||
tf[j][2] += fO[2];
|
||||
|
||||
tf[jH1][0] += fH[0];
|
||||
tf[jH1][1] += fH[1];
|
||||
tf[jH1][2] += fH[2];
|
||||
|
||||
tf[jH2][0] += fH[0];
|
||||
tf[jH2][1] += fH[1];
|
||||
tf[jH2][2] += fH[2];
|
||||
|
||||
delx1 = x[j][0] - x1[0];
|
||||
dely1 = x[j][1] - x1[1];
|
||||
delz1 = x[j][2] - x1[2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
delx2 = x[jH1][0] - x1[0];
|
||||
dely2 = x[jH1][1] - x1[1];
|
||||
delz2 = x[jH1][2] - x1[2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
delx3 = x[jH2][0] - x1[0];
|
||||
dely3 = x[jH2][1] - x1[1];
|
||||
delz3 = x[jH2][2] - x1[2];
|
||||
domain->minimum_image(&delx3,&dely3,&delz3);
|
||||
|
||||
tvirial[0] += 0.5 * (delx1 * fO[0] + (delx2 + delx3) * fH[0]);
|
||||
tvirial[1] += 0.5 * (dely1 * fO[1] + (dely2 + dely3) * fH[1]);
|
||||
tvirial[2] += 0.5 * (delz1 * fO[2] + (delz2 + delz3) * fH[2]);
|
||||
tvirial[3] += 0.5 * (dely1 * fO[0] + (dely2 + dely3) * fH[0]);
|
||||
tvirial[4] += 0.5 * (delz1 * fO[0] + (delz2 + delz3) * fH[0]);
|
||||
tvirial[5] += 0.5 * (delz1 * fO[1] + (delz2 + delz3) * fH[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (eflag) {
|
||||
if (!ncoultablebits || rsq <= tabinnersq)
|
||||
phicoul = prefactor*erfc;
|
||||
else {
|
||||
table = etable[itable] + fraction*detable[itable];
|
||||
phicoul = qtmp*q[j] * table;
|
||||
}
|
||||
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
|
||||
eng_coul += phicoul;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vflag == 2) {
|
||||
virial_compute();
|
||||
for (int i = 0; i < 6; i++) virial[i] += tvirial[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 6 || narg > 7) error->all("Illegal pair_style command");
|
||||
|
||||
typeO = atoi(arg[0]);
|
||||
typeH = atoi(arg[1]);
|
||||
typeB = atoi(arg[2]);
|
||||
typeA = atoi(arg[3]);
|
||||
qdist = atof(arg[4]);
|
||||
|
||||
cut_lj_global = atof(arg[5]);
|
||||
if (narg == 6) cut_coul = cut_lj_global;
|
||||
else cut_coul = atof(arg[6]);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
|
||||
if (allocated) {
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i+1; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::init_style()
|
||||
{
|
||||
int i,j;
|
||||
|
||||
if (atom->tag_enable == 0)
|
||||
error->all("Pair style lj/cut/coul/long/tip4p requires atom IDs");
|
||||
if (!force->newton_pair)
|
||||
error->all("Pair style lj/cut/coul/long/tip4p requires newton pair on");
|
||||
if (atom->charge_allow == 0)
|
||||
error->all("Must use charged atom style with this pair style");
|
||||
|
||||
cut_coulsq = cut_coul * cut_coul;
|
||||
|
||||
// set & error check interior rRESPA cutoffs
|
||||
|
||||
if (strcmp(update->integrate_style,"respa") == 0) {
|
||||
if (((Respa *) update->integrate)->level_inner >= 0) {
|
||||
cut_respa = ((Respa *) update->integrate)->cutoff;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++)
|
||||
if (MIN(cut_lj[i][j],cut_coul) < cut_respa[3])
|
||||
error->all("Pair cutoff < Respa interior cutoff");
|
||||
}
|
||||
} else cut_respa = NULL;
|
||||
|
||||
// insure use of correct KSpace long-range solver, set g_ewald
|
||||
|
||||
if (force->kspace == NULL)
|
||||
error->all("Pair style is incompatible with KSpace style");
|
||||
if (strcmp(force->kspace_style,"pppm/tip4p") == 0)
|
||||
g_ewald = force->kspace->g_ewald;
|
||||
else error->all("Pair style is incompatible with KSpace style");
|
||||
|
||||
// setup force tables
|
||||
|
||||
if (ncoultablebits) init_tables();
|
||||
|
||||
// set alpha parameter
|
||||
|
||||
double theta = force->angle->equilibrium_angle(typeA);
|
||||
double blen = force->bond->equilibrium_distance(typeB);
|
||||
alpha = qdist / (2.0 * cos(0.5*theta) * blen);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::write_restart_settings(FILE *fp)
|
||||
{
|
||||
fwrite(&typeO,sizeof(int),1,fp);
|
||||
fwrite(&typeH,sizeof(int),1,fp);
|
||||
fwrite(&typeB,sizeof(int),1,fp);
|
||||
fwrite(&typeA,sizeof(int),1,fp);
|
||||
fwrite(&qdist,sizeof(double),1,fp);
|
||||
|
||||
fwrite(&cut_lj_global,sizeof(double),1,fp);
|
||||
fwrite(&cut_coul,sizeof(double),1,fp);
|
||||
fwrite(&offset_flag,sizeof(int),1,fp);
|
||||
fwrite(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::read_restart_settings(FILE *fp)
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
fread(&typeO,sizeof(int),1,fp);
|
||||
fread(&typeH,sizeof(int),1,fp);
|
||||
fread(&typeB,sizeof(int),1,fp);
|
||||
fread(&typeA,sizeof(int),1,fp);
|
||||
fread(&qdist,sizeof(double),1,fp);
|
||||
|
||||
fread(&cut_lj_global,sizeof(double),1,fp);
|
||||
fread(&cut_coul,sizeof(double),1,fp);
|
||||
fread(&offset_flag,sizeof(int),1,fp);
|
||||
fread(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
|
||||
MPI_Bcast(&typeO,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&typeH,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&typeB,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&typeA,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&qdist,1,MPI_DOUBLE,0,world);
|
||||
|
||||
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
find 2 H atoms bonded to O atom i
|
||||
compute position xM of fictitious charge site for O atom
|
||||
also return local indices iH1,iH2 of H atoms
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairLJCutCoulLongTIP4P::find_M(int i, int &iH1, int &iH2, double *xM)
|
||||
{
|
||||
// test that O is correctly bonded to 2 succesive H atoms
|
||||
|
||||
iH1 = atom->map(atom->tag[i] + 1);
|
||||
iH2 = atom->map(atom->tag[i] + 2);
|
||||
|
||||
if (iH1 == -1 || iH2 == -1) error->one("TIP4P hydrogen is missing");
|
||||
if (atom->type[iH1] != typeH || atom->type[iH2] != typeH)
|
||||
error->one("TIP4P hydrogen has incorrect atom type");
|
||||
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[iH1][0] - x[i][0];
|
||||
double dely1 = x[iH1][1] - x[i][1];
|
||||
double delz1 = x[iH1][2] - x[i][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
double delx2 = x[iH2][0] - x[i][0];
|
||||
double dely2 = x[iH2][1] - x[i][1];
|
||||
double delz2 = x[iH2][2] - x[i][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
xM[0] = x[i][0] + alpha * (delx1 + delx2);
|
||||
xM[1] = x[i][1] + alpha * (dely1 + dely2);
|
||||
xM[2] = x[i][2] + alpha * (delz1 + delz2);
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PAIR_LJ_CUT_COUL_LONG_TIP4P_H
|
||||
#define PAIR_LJ_CUT_COUL_LONG_TIP4P_H
|
||||
|
||||
#include "pair_lj_cut_coul_long.h"
|
||||
|
||||
class PairLJCutCoulLongTIP4P : public PairLJCutCoulLong {
|
||||
friend class PPPM;
|
||||
|
||||
public:
|
||||
PairLJCutCoulLongTIP4P();
|
||||
void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void init_style();
|
||||
void write_restart_settings(FILE *fp);
|
||||
void read_restart_settings(FILE *fp);
|
||||
|
||||
private:
|
||||
int typeH,typeO; // atom types of TIP4P water H and O atoms
|
||||
int typeA,typeB; // angle and bond types of TIP4P water
|
||||
double qdist; // distance from O site to negative charge
|
||||
double alpha; // geometric constraint parameter for TIP4P
|
||||
double **tf;
|
||||
double tvirial[6];
|
||||
|
||||
void find_M(int, int &, int &, double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
1868
src/pppm.cpp
1868
src/pppm.cpp
File diff suppressed because it is too large
Load Diff
94
src/pppm.h
94
src/pppm.h
@ -1,94 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PPPM_H
|
||||
#define PPPM_H
|
||||
|
||||
#include "kspace.h"
|
||||
|
||||
class FFT3d;
|
||||
class Remap;
|
||||
|
||||
class PPPM : public KSpace {
|
||||
public:
|
||||
PPPM(int, char **);
|
||||
~PPPM();
|
||||
void init();
|
||||
void setup();
|
||||
void compute(int, int);
|
||||
void timing(int, double &, double &);
|
||||
int memory_usage();
|
||||
|
||||
protected:
|
||||
int me,nprocs;
|
||||
double PI;
|
||||
double precision;
|
||||
int nfactors;
|
||||
int *factors;
|
||||
double qsum,qsqsum;
|
||||
double qqrd2e;
|
||||
double cutoff;
|
||||
double volume;
|
||||
double delxinv,delyinv,delzinv,delvolinv;
|
||||
double shift,shiftone;
|
||||
|
||||
int nxlo_in,nylo_in,nzlo_in,nxhi_in,nyhi_in,nzhi_in;
|
||||
int nxlo_out,nylo_out,nzlo_out,nxhi_out,nyhi_out,nzhi_out;
|
||||
int nxlo_ghost,nxhi_ghost,nylo_ghost,nyhi_ghost,nzlo_ghost,nzhi_ghost;
|
||||
int nxlo_fft,nylo_fft,nzlo_fft,nxhi_fft,nyhi_fft,nzhi_fft;
|
||||
int nlower,nupper;
|
||||
int ngrid,nfft,nbuf,nfft_both;
|
||||
|
||||
double ***density_brick;
|
||||
double ***vdx_brick,***vdy_brick,***vdz_brick;
|
||||
double *greensfn;
|
||||
double **vg;
|
||||
double *fkx,*fky,*fkz;
|
||||
double *density_fft;
|
||||
double *work1,*work2;
|
||||
double *buf1,*buf2;
|
||||
|
||||
double *gf_b;
|
||||
double **rho1d,**rho_coeff;
|
||||
|
||||
FFT3d *fft1,*fft2;
|
||||
Remap *remap;
|
||||
|
||||
int **part2grid; // storage for particle -> grid mapping
|
||||
int nmax;
|
||||
|
||||
// TIP4P settings
|
||||
int typeH,typeO; // atom types of TIP4P water H and O atoms
|
||||
double qdist; // distance from O site to negative charge
|
||||
double alpha; // geometric factor
|
||||
|
||||
void set_grid();
|
||||
void allocate();
|
||||
void deallocate();
|
||||
int factorable(int);
|
||||
double rms(double, double, double, double, double **);
|
||||
void compute_gf_denom();
|
||||
double gf_denom(double, double, double);
|
||||
virtual void particle_map();
|
||||
virtual void make_rho();
|
||||
void brick2fft();
|
||||
void fillbrick();
|
||||
void poisson(int, int);
|
||||
virtual void fieldforce();
|
||||
void procs2grid2d(int,int,int,int *, int*);
|
||||
void compute_rho1d(double, double, double);
|
||||
void compute_rho_coeff();
|
||||
void slabcorr(int);
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,261 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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 authors: Amalie Frischknecht and Ahmed Ismail (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "math.h"
|
||||
#include "pppm_tip4p.h"
|
||||
#include "atom.h"
|
||||
#include "domain.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
#define OFFSET 4096
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PPPMTIP4P::PPPMTIP4P(int narg, char **arg) : PPPM(narg, arg) {}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
find center grid pt for each of my particles
|
||||
check that full stencil for the particle will fit in my 3d brick
|
||||
store central grid pt indices in part2grid array
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PPPMTIP4P::particle_map()
|
||||
{
|
||||
int nx,ny,nz,iH1,iH2;
|
||||
double *xi,xM[3];
|
||||
|
||||
int *type = atom->type;
|
||||
double **x = atom->x;
|
||||
int nlocal = atom->nlocal;
|
||||
double boxxlo = domain->boxxlo;
|
||||
double boxylo = domain->boxylo;
|
||||
double boxzlo = domain->boxzlo;
|
||||
|
||||
int flag = 0;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (type[i] == typeO) {
|
||||
find_M(i,iH1,iH2,xM);
|
||||
xi = xM;
|
||||
} else xi = x[i];
|
||||
|
||||
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
|
||||
// current particle coord can be outside global and local box
|
||||
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
|
||||
|
||||
nx = static_cast<int> ((xi[0]-boxxlo)*delxinv+shift) - OFFSET;
|
||||
ny = static_cast<int> ((xi[1]-boxylo)*delyinv+shift) - OFFSET;
|
||||
nz = static_cast<int> ((xi[2]-boxzlo)*delzinv+shift) - OFFSET;
|
||||
|
||||
part2grid[i][0] = nx;
|
||||
part2grid[i][1] = ny;
|
||||
part2grid[i][2] = nz;
|
||||
|
||||
// check that entire stencil around nx,ny,nz will fit in my 3d brick
|
||||
|
||||
if (nx+nlower < nxlo_out || nx+nupper > nxhi_out ||
|
||||
ny+nlower < nylo_out || ny+nupper > nyhi_out ||
|
||||
nz+nlower < nzlo_out || nz+nupper > nzhi_out) flag++;
|
||||
}
|
||||
|
||||
int flag_all;
|
||||
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
|
||||
if (flag_all) error->all("Out of range atoms - cannot compute PPPM");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create discretized "density" on section of global grid due to my particles
|
||||
density(x,y,z) = charge "density" at grid points of my 3d brick
|
||||
(nxlo:nxhi,nylo:nyhi,nzlo:nzhi) is extent of my brick (including ghosts)
|
||||
in global grid
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PPPMTIP4P::make_rho()
|
||||
{
|
||||
int i,l,m,n,nx,ny,nz,mx,my,mz,iH1,iH2;
|
||||
double dx,dy,dz,x0,y0,z0;
|
||||
double *xi,xM[3];
|
||||
|
||||
// clear 3d density array
|
||||
|
||||
double *vec = &density_brick[nzlo_out][nylo_out][nxlo_out];
|
||||
for (i = 0; i < ngrid; i++) vec[i] = 0.0;
|
||||
|
||||
// loop over my charges, add their contribution to nearby grid points
|
||||
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
|
||||
// (dx,dy,dz) = distance to "lower left" grid pt
|
||||
// (mx,my,mz) = global coords of moving stencil pt
|
||||
|
||||
int *type = atom->type;
|
||||
double *q = atom->q;
|
||||
double **x = atom->x;
|
||||
int nlocal = atom->nlocal;
|
||||
double boxxlo = domain->boxxlo;
|
||||
double boxylo = domain->boxylo;
|
||||
double boxzlo = domain->boxzlo;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (type[i] == typeO) {
|
||||
find_M(i,iH1,iH2,xM);
|
||||
xi = xM;
|
||||
} else xi = x[i];
|
||||
|
||||
nx = part2grid[i][0];
|
||||
ny = part2grid[i][1];
|
||||
nz = part2grid[i][2];
|
||||
dx = nx+shiftone - (xi[0]-boxxlo)*delxinv;
|
||||
dy = ny+shiftone - (xi[1]-boxylo)*delyinv;
|
||||
dz = nz+shiftone - (xi[2]-boxzlo)*delzinv;
|
||||
|
||||
compute_rho1d(dx,dy,dz);
|
||||
|
||||
z0 = delvolinv * q[i];
|
||||
for (n = nlower; n <= nupper; n++) {
|
||||
mz = n+nz;
|
||||
y0 = z0*rho1d[2][n];
|
||||
for (m = nlower; m <= nupper; m++) {
|
||||
my = m+ny;
|
||||
x0 = y0*rho1d[1][m];
|
||||
for (l = nlower; l <= nupper; l++) {
|
||||
mx = l+nx;
|
||||
density_brick[mz][my][mx] += x0*rho1d[0][l];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
interpolate from grid to get electric field & force on my particles
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PPPMTIP4P::fieldforce()
|
||||
{
|
||||
int i,l,m,n,nx,ny,nz,mx,my,mz;
|
||||
double dx,dy,dz,x0,y0,z0;
|
||||
double ek[3];
|
||||
double *xi;
|
||||
int iH1,iH2;
|
||||
double xM[3];
|
||||
double fx,fy,fz;
|
||||
|
||||
// loop over my charges, interpolate electric field from nearby grid points
|
||||
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
|
||||
// (dx,dy,dz) = distance to "lower left" grid pt
|
||||
// (mx,my,mz) = global coords of moving stencil pt
|
||||
// ek = 3 components of E-field on particle
|
||||
|
||||
double *q = atom->q;
|
||||
double **x = atom->x;
|
||||
double **f = atom->f;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
double boxxlo = domain->boxxlo;
|
||||
double boxylo = domain->boxylo;
|
||||
double boxzlo = domain->boxzlo;
|
||||
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (type[i] == typeO) {
|
||||
find_M(i,iH1,iH2,xM);
|
||||
xi = xM;
|
||||
} else xi = x[i];
|
||||
|
||||
nx = part2grid[i][0];
|
||||
ny = part2grid[i][1];
|
||||
nz = part2grid[i][2];
|
||||
dx = nx+shiftone - (xi[0]-boxxlo)*delxinv;
|
||||
dy = ny+shiftone - (xi[1]-boxylo)*delyinv;
|
||||
dz = nz+shiftone - (xi[2]-boxzlo)*delzinv;
|
||||
|
||||
compute_rho1d(dx,dy,dz);
|
||||
|
||||
ek[0] = ek[1] = ek[2] = 0.0;
|
||||
for (n = nlower; n <= nupper; n++) {
|
||||
mz = n+nz;
|
||||
z0 = rho1d[2][n];
|
||||
for (m = nlower; m <= nupper; m++) {
|
||||
my = m+ny;
|
||||
y0 = z0*rho1d[1][m];
|
||||
for (l = nlower; l <= nupper; l++) {
|
||||
mx = l+nx;
|
||||
x0 = y0*rho1d[0][l];
|
||||
ek[0] -= x0*vdx_brick[mz][my][mx];
|
||||
ek[1] -= x0*vdy_brick[mz][my][mx];
|
||||
ek[2] -= x0*vdz_brick[mz][my][mx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert E-field to force
|
||||
|
||||
if (type[i] != typeO) {
|
||||
f[i][0] += qqrd2e*q[i]*ek[0];
|
||||
f[i][1] += qqrd2e*q[i]*ek[1];
|
||||
f[i][2] += qqrd2e*q[i]*ek[2];
|
||||
} else {
|
||||
|
||||
fx = qqrd2e * q[i] * ek[0];
|
||||
fy = qqrd2e * q[i] * ek[1];
|
||||
fz = qqrd2e * q[i] * ek[2];
|
||||
find_M(i,iH1,iH2,xM);
|
||||
|
||||
f[i][0] += fx*(1.0-2.0*alpha);
|
||||
f[i][1] += fy*(1.0-2.0*alpha);
|
||||
f[i][2] += fz*(1.0-2.0*alpha);
|
||||
|
||||
f[iH1][0] += alpha*(fx);
|
||||
f[iH1][1] += alpha*(fy);
|
||||
f[iH1][2] += alpha*(fz);
|
||||
|
||||
f[iH2][0] += alpha*(fx);
|
||||
f[iH2][1] += alpha*(fy);
|
||||
f[iH2][2] += alpha*(fz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
find 2 H atoms bonded to O atom i
|
||||
compute position xM of fictitious charge site for O atom
|
||||
also return local indices iH1,iH2 of H atoms
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PPPMTIP4P::find_M(int i, int &iH1, int &iH2, double *xM)
|
||||
{
|
||||
iH1 = atom->map(atom->tag[i] + 1);
|
||||
iH2 = atom->map(atom->tag[i] + 2);
|
||||
|
||||
if (iH1 == -1 || iH2 == -1) error->one("TIP4P hydrogen is missing");
|
||||
if (atom->type[iH1] != typeH || atom->type[iH2] != typeH)
|
||||
error->one("TIP4P hydrogen has incorrect atom type");
|
||||
|
||||
double **x = atom->x;
|
||||
|
||||
double delx1 = x[iH1][0] - x[i][0];
|
||||
double dely1 = x[iH1][1] - x[i][1];
|
||||
double delz1 = x[iH1][2] - x[i][2];
|
||||
domain->minimum_image(&delx1,&dely1,&delz1);
|
||||
|
||||
double delx2 = x[iH2][0] - x[i][0];
|
||||
double dely2 = x[iH2][1] - x[i][1];
|
||||
double delz2 = x[iH2][2] - x[i][2];
|
||||
domain->minimum_image(&delx2,&dely2,&delz2);
|
||||
|
||||
xM[0] = x[i][0] + alpha * (delx1 + delx2);
|
||||
xM[1] = x[i][1] + alpha * (dely1 + dely2);
|
||||
xM[2] = x[i][2] + alpha * (delz1 + delz2);
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef PPPM_TIP4P_H
|
||||
#define PPPM_TIP4P_H
|
||||
|
||||
#include "pppm.h"
|
||||
|
||||
class PPPMTIP4P : public PPPM {
|
||||
public:
|
||||
PPPMTIP4P(int, char **);
|
||||
|
||||
private:
|
||||
void particle_map();
|
||||
void make_rho();
|
||||
void fieldforce();
|
||||
|
||||
void find_M(int, int &, int &, double *);
|
||||
};
|
||||
|
||||
#endif
|
||||
506
src/remap.cpp
506
src/remap.cpp
@ -1,506 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "remap.h"
|
||||
#include "pack.h"
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Data layout for 3d remaps:
|
||||
|
||||
data set of Nfast x Nmid x Nslow elements is owned by P procs
|
||||
each element = nqty contiguous datums
|
||||
on input, each proc owns a subsection of the elements
|
||||
on output, each proc will own a (presumably different) subsection
|
||||
my subsection must not overlap with any other proc's subsection,
|
||||
i.e. the union of all proc's input (or output) subsections must
|
||||
exactly tile the global Nfast x Nmid x Nslow data set
|
||||
when called from C, all subsection indices are
|
||||
C-style from 0 to N-1 where N = Nfast or Nmid or Nslow
|
||||
when called from F77, all subsection indices are
|
||||
F77-style from 1 to N where N = Nfast or Nmid or Nslow
|
||||
a proc can own 0 elements on input or output
|
||||
by specifying hi index < lo index
|
||||
on both input and output, data is stored contiguously on a processor
|
||||
with a fast-varying, mid-varying, and slow-varying index
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Perform 3d remap
|
||||
|
||||
Arguments:
|
||||
in starting address of input data on this proc
|
||||
out starting address of where output data for this proc
|
||||
will be placed (can be same as in)
|
||||
buf extra memory required for remap
|
||||
if memory=0 was used in call to remap_3d_create_plan
|
||||
then buf must be big enough to hold output result
|
||||
i.e. nqty * (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
|
||||
(out_khi-out_klo+1)
|
||||
if memory=1 was used in call to remap_3d_create_plan
|
||||
then buf is not used, can just be a dummy pointer
|
||||
plan plan returned by previous call to remap_3d_create_plan
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void remap_3d(double *in, double *out, double *buf,
|
||||
struct remap_plan_3d *plan)
|
||||
|
||||
{
|
||||
MPI_Status status;
|
||||
int i,isend,irecv;
|
||||
double *scratch;
|
||||
|
||||
if (plan->memory == 0)
|
||||
scratch = buf;
|
||||
else
|
||||
scratch = plan->scratch;
|
||||
|
||||
// post all recvs into scratch space
|
||||
|
||||
for (irecv = 0; irecv < plan->nrecv; irecv++)
|
||||
MPI_Irecv(&scratch[plan->recv_bufloc[irecv]],plan->recv_size[irecv],
|
||||
MPI_DOUBLE,plan->recv_proc[irecv],0,
|
||||
plan->comm,&plan->request[irecv]);
|
||||
|
||||
// send all messages to other procs
|
||||
|
||||
for (isend = 0; isend < plan->nsend; isend++) {
|
||||
plan->pack(&in[plan->send_offset[isend]],
|
||||
plan->sendbuf,&plan->packplan[isend]);
|
||||
MPI_Send(plan->sendbuf,plan->send_size[isend],MPI_DOUBLE,
|
||||
plan->send_proc[isend],0,plan->comm);
|
||||
}
|
||||
|
||||
// copy in -> scratch -> out for self data
|
||||
|
||||
if (plan->self) {
|
||||
isend = plan->nsend;
|
||||
irecv = plan->nrecv;
|
||||
plan->pack(&in[plan->send_offset[isend]],
|
||||
&scratch[plan->recv_bufloc[irecv]],
|
||||
&plan->packplan[isend]);
|
||||
plan->unpack(&scratch[plan->recv_bufloc[irecv]],
|
||||
&out[plan->recv_offset[irecv]],&plan->unpackplan[irecv]);
|
||||
}
|
||||
|
||||
// unpack all messages from scratch -> out
|
||||
|
||||
for (i = 0; i < plan->nrecv; i++) {
|
||||
MPI_Waitany(plan->nrecv,plan->request,&irecv,&status);
|
||||
plan->unpack(&scratch[plan->recv_bufloc[irecv]],
|
||||
&out[plan->recv_offset[irecv]],&plan->unpackplan[irecv]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Create plan for performing a 3d remap
|
||||
|
||||
Arguments:
|
||||
comm MPI communicator for the P procs which own the data
|
||||
in_ilo,in_ihi input bounds of data I own in fast index
|
||||
in_jlo,in_jhi input bounds of data I own in mid index
|
||||
in_klo,in_khi input bounds of data I own in slow index
|
||||
out_ilo,out_ihi output bounds of data I own in fast index
|
||||
out_jlo,out_jhi output bounds of data I own in mid index
|
||||
out_klo,out_khi output bounds of data I own in slow index
|
||||
nqty # of datums per element
|
||||
permute permutation in storage order of indices on output
|
||||
0 = no permutation
|
||||
1 = permute once = mid->fast, slow->mid, fast->slow
|
||||
2 = permute twice = slow->fast, fast->mid, mid->slow
|
||||
memory user provides buffer memory for remap or system does
|
||||
0 = user provides memory
|
||||
1 = system provides memory
|
||||
precision precision of data
|
||||
1 = single precision (4 bytes per datum)
|
||||
2 = double precision (8 bytes per datum)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
struct remap_plan_3d *remap_3d_create_plan(
|
||||
MPI_Comm comm,
|
||||
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
|
||||
int in_klo, int in_khi,
|
||||
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
|
||||
int out_klo, int out_khi,
|
||||
int nqty, int permute, int memory, int precision)
|
||||
|
||||
{
|
||||
struct remap_plan_3d *plan;
|
||||
struct extent_3d *array;
|
||||
struct extent_3d in,out,overlap;
|
||||
int i,iproc,nsend,nrecv,ibuf,size,me,nprocs;
|
||||
|
||||
// query MPI info
|
||||
|
||||
MPI_Comm_rank(comm,&me);
|
||||
MPI_Comm_size(comm,&nprocs);
|
||||
|
||||
// single precision not yet supported
|
||||
|
||||
if (precision == 1) {
|
||||
if (me == 0) printf("Single precision not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate memory for plan data struct
|
||||
|
||||
plan = (struct remap_plan_3d *) malloc(sizeof(struct remap_plan_3d));
|
||||
if (plan == NULL) return NULL;
|
||||
|
||||
// store parameters in local data structs
|
||||
|
||||
in.ilo = in_ilo;
|
||||
in.ihi = in_ihi;
|
||||
in.isize = in.ihi - in.ilo + 1;
|
||||
|
||||
in.jlo = in_jlo;
|
||||
in.jhi = in_jhi;
|
||||
in.jsize = in.jhi - in.jlo + 1;
|
||||
|
||||
in.klo = in_klo;
|
||||
in.khi = in_khi;
|
||||
in.ksize = in.khi - in.klo + 1;
|
||||
|
||||
out.ilo = out_ilo;
|
||||
out.ihi = out_ihi;
|
||||
out.isize = out.ihi - out.ilo + 1;
|
||||
|
||||
out.jlo = out_jlo;
|
||||
out.jhi = out_jhi;
|
||||
out.jsize = out.jhi - out.jlo + 1;
|
||||
|
||||
out.klo = out_klo;
|
||||
out.khi = out_khi;
|
||||
out.ksize = out.khi - out.klo + 1;
|
||||
|
||||
// combine output extents across all procs
|
||||
|
||||
array = (struct extent_3d *) malloc(nprocs*sizeof(struct extent_3d));
|
||||
if (array == NULL) return NULL;
|
||||
|
||||
MPI_Allgather(&out,sizeof(struct extent_3d),MPI_BYTE,
|
||||
array,sizeof(struct extent_3d),MPI_BYTE,comm);
|
||||
|
||||
// count send collides, including self
|
||||
|
||||
nsend = 0;
|
||||
iproc = me;
|
||||
for (i = 0; i < nprocs; i++) {
|
||||
iproc++;
|
||||
if (iproc == nprocs) iproc = 0;
|
||||
nsend += remap_3d_collide(&in,&array[iproc],&overlap);
|
||||
}
|
||||
|
||||
// malloc space for send info
|
||||
|
||||
if (nsend) {
|
||||
if (precision == 1)
|
||||
plan->pack = NULL;
|
||||
else
|
||||
plan->pack = pack_3d;
|
||||
|
||||
plan->send_offset = (int *) malloc(nsend*sizeof(int));
|
||||
plan->send_size = (int *) malloc(nsend*sizeof(int));
|
||||
plan->send_proc = (int *) malloc(nsend*sizeof(int));
|
||||
plan->packplan = (struct pack_plan_3d *)
|
||||
malloc(nsend*sizeof(struct pack_plan_3d));
|
||||
|
||||
if (plan->send_offset == NULL || plan->send_size == NULL ||
|
||||
plan->send_proc == NULL || plan->packplan == NULL) return NULL;
|
||||
}
|
||||
|
||||
// store send info, with self as last entry
|
||||
|
||||
nsend = 0;
|
||||
iproc = me;
|
||||
for (i = 0; i < nprocs; i++) {
|
||||
iproc++;
|
||||
if (iproc == nprocs) iproc = 0;
|
||||
if (remap_3d_collide(&in,&array[iproc],&overlap)) {
|
||||
plan->send_proc[nsend] = iproc;
|
||||
plan->send_offset[nsend] = nqty *
|
||||
((overlap.klo-in.klo)*in.jsize*in.isize +
|
||||
((overlap.jlo-in.jlo)*in.isize + overlap.ilo-in.ilo));
|
||||
plan->packplan[nsend].nfast = nqty*overlap.isize;
|
||||
plan->packplan[nsend].nmid = overlap.jsize;
|
||||
plan->packplan[nsend].nslow = overlap.ksize;
|
||||
plan->packplan[nsend].nstride_line = nqty*in.isize;
|
||||
plan->packplan[nsend].nstride_plane = nqty*in.jsize*in.isize;
|
||||
plan->packplan[nsend].nqty = nqty;
|
||||
plan->send_size[nsend] = nqty*overlap.isize*overlap.jsize*overlap.ksize;
|
||||
nsend++;
|
||||
}
|
||||
}
|
||||
|
||||
// plan->nsend = # of sends not including self
|
||||
|
||||
if (nsend && plan->send_proc[nsend-1] == me)
|
||||
plan->nsend = nsend - 1;
|
||||
else
|
||||
plan->nsend = nsend;
|
||||
|
||||
// combine input extents across all procs
|
||||
|
||||
MPI_Allgather(&in,sizeof(struct extent_3d),MPI_BYTE,
|
||||
array,sizeof(struct extent_3d),MPI_BYTE,comm);
|
||||
|
||||
// count recv collides, including self
|
||||
|
||||
nrecv = 0;
|
||||
iproc = me;
|
||||
for (i = 0; i < nprocs; i++) {
|
||||
iproc++;
|
||||
if (iproc == nprocs) iproc = 0;
|
||||
nrecv += remap_3d_collide(&out,&array[iproc],&overlap);
|
||||
}
|
||||
|
||||
// malloc space for recv info
|
||||
|
||||
if (nrecv) {
|
||||
if (precision == 1) {
|
||||
if (permute == 0)
|
||||
plan->unpack = NULL;
|
||||
else if (permute == 1) {
|
||||
if (nqty == 1)
|
||||
plan->unpack = NULL;
|
||||
else if (nqty == 2)
|
||||
plan->unpack = NULL;
|
||||
else
|
||||
plan->unpack = NULL;
|
||||
}
|
||||
else if (permute == 2) {
|
||||
if (nqty == 1)
|
||||
plan->unpack = NULL;
|
||||
else if (nqty == 2)
|
||||
plan->unpack = NULL;
|
||||
else
|
||||
plan->unpack = NULL;
|
||||
}
|
||||
}
|
||||
else if (precision == 2) {
|
||||
if (permute == 0)
|
||||
plan->unpack = unpack_3d;
|
||||
else if (permute == 1) {
|
||||
if (nqty == 1)
|
||||
plan->unpack = unpack_3d_permute1_1;
|
||||
else if (nqty == 2)
|
||||
plan->unpack = unpack_3d_permute1_2;
|
||||
else
|
||||
plan->unpack = unpack_3d_permute1_n;
|
||||
}
|
||||
else if (permute == 2) {
|
||||
if (nqty == 1)
|
||||
plan->unpack = unpack_3d_permute2_1;
|
||||
else if (nqty == 2)
|
||||
plan->unpack = unpack_3d_permute2_2;
|
||||
else
|
||||
plan->unpack = unpack_3d_permute2_n;
|
||||
}
|
||||
}
|
||||
|
||||
plan->recv_offset = (int *) malloc(nrecv*sizeof(int));
|
||||
plan->recv_size = (int *) malloc(nrecv*sizeof(int));
|
||||
plan->recv_proc = (int *) malloc(nrecv*sizeof(int));
|
||||
plan->recv_bufloc = (int *) malloc(nrecv*sizeof(int));
|
||||
plan->request = (MPI_Request *) malloc(nrecv*sizeof(MPI_Request));
|
||||
plan->unpackplan = (struct pack_plan_3d *)
|
||||
malloc(nrecv*sizeof(struct pack_plan_3d));
|
||||
|
||||
if (plan->recv_offset == NULL || plan->recv_size == NULL ||
|
||||
plan->recv_proc == NULL || plan->recv_bufloc == NULL ||
|
||||
plan->request == NULL || plan->unpackplan == NULL) return NULL;
|
||||
}
|
||||
|
||||
// store recv info, with self as last entry
|
||||
|
||||
ibuf = 0;
|
||||
nrecv = 0;
|
||||
iproc = me;
|
||||
|
||||
for (i = 0; i < nprocs; i++) {
|
||||
iproc++;
|
||||
if (iproc == nprocs) iproc = 0;
|
||||
if (remap_3d_collide(&out,&array[iproc],&overlap)) {
|
||||
plan->recv_proc[nrecv] = iproc;
|
||||
plan->recv_bufloc[nrecv] = ibuf;
|
||||
|
||||
if (permute == 0) {
|
||||
plan->recv_offset[nrecv] = nqty *
|
||||
((overlap.klo-out.klo)*out.jsize*out.isize +
|
||||
(overlap.jlo-out.jlo)*out.isize + (overlap.ilo-out.ilo));
|
||||
plan->unpackplan[nrecv].nfast = nqty*overlap.isize;
|
||||
plan->unpackplan[nrecv].nmid = overlap.jsize;
|
||||
plan->unpackplan[nrecv].nslow = overlap.ksize;
|
||||
plan->unpackplan[nrecv].nstride_line = nqty*out.isize;
|
||||
plan->unpackplan[nrecv].nstride_plane = nqty*out.jsize*out.isize;
|
||||
plan->unpackplan[nrecv].nqty = nqty;
|
||||
}
|
||||
else if (permute == 1) {
|
||||
plan->recv_offset[nrecv] = nqty *
|
||||
((overlap.ilo-out.ilo)*out.ksize*out.jsize +
|
||||
(overlap.klo-out.klo)*out.jsize + (overlap.jlo-out.jlo));
|
||||
plan->unpackplan[nrecv].nfast = overlap.isize;
|
||||
plan->unpackplan[nrecv].nmid = overlap.jsize;
|
||||
plan->unpackplan[nrecv].nslow = overlap.ksize;
|
||||
plan->unpackplan[nrecv].nstride_line = nqty*out.jsize;
|
||||
plan->unpackplan[nrecv].nstride_plane = nqty*out.ksize*out.jsize;
|
||||
plan->unpackplan[nrecv].nqty = nqty;
|
||||
}
|
||||
else {
|
||||
plan->recv_offset[nrecv] = nqty *
|
||||
((overlap.jlo-out.jlo)*out.isize*out.ksize +
|
||||
(overlap.ilo-out.ilo)*out.ksize + (overlap.klo-out.klo));
|
||||
plan->unpackplan[nrecv].nfast = overlap.isize;
|
||||
plan->unpackplan[nrecv].nmid = overlap.jsize;
|
||||
plan->unpackplan[nrecv].nslow = overlap.ksize;
|
||||
plan->unpackplan[nrecv].nstride_line = nqty*out.ksize;
|
||||
plan->unpackplan[nrecv].nstride_plane = nqty*out.isize*out.ksize;
|
||||
plan->unpackplan[nrecv].nqty = nqty;
|
||||
}
|
||||
|
||||
plan->recv_size[nrecv] = nqty*overlap.isize*overlap.jsize*overlap.ksize;
|
||||
ibuf += plan->recv_size[nrecv];
|
||||
nrecv++;
|
||||
}
|
||||
}
|
||||
|
||||
// plan->nrecv = # of recvs not including self
|
||||
|
||||
if (nrecv && plan->recv_proc[nrecv-1] == me)
|
||||
plan->nrecv = nrecv - 1;
|
||||
else
|
||||
plan->nrecv = nrecv;
|
||||
|
||||
// init remaining fields in remap plan
|
||||
|
||||
plan->memory = memory;
|
||||
|
||||
if (nrecv == plan->nrecv)
|
||||
plan->self = 0;
|
||||
else
|
||||
plan->self = 1;
|
||||
|
||||
// free locally malloced space
|
||||
|
||||
free(array);
|
||||
|
||||
// find biggest send message (not including self) and malloc space for it
|
||||
|
||||
plan->sendbuf = NULL;
|
||||
|
||||
size = 0;
|
||||
for (nsend = 0; nsend < plan->nsend; nsend++)
|
||||
size = MAX(size,plan->send_size[nsend]);
|
||||
|
||||
if (size) {
|
||||
if (precision == 1)
|
||||
plan->sendbuf = NULL;
|
||||
else
|
||||
plan->sendbuf = (double *) malloc(size*sizeof(double));
|
||||
if (plan->sendbuf == NULL) return NULL;
|
||||
}
|
||||
|
||||
// if requested, allocate internal scratch space for recvs,
|
||||
// only need it if I will receive any data (including self)
|
||||
|
||||
plan->scratch = NULL;
|
||||
|
||||
if (memory == 1) {
|
||||
if (nrecv > 0) {
|
||||
if (precision == 1)
|
||||
plan->scratch = NULL;
|
||||
else
|
||||
plan->scratch =
|
||||
(double *) malloc(nqty*out.isize*out.jsize*out.ksize*sizeof(double));
|
||||
if (plan->scratch == NULL) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// create new MPI communicator for remap
|
||||
|
||||
MPI_Comm_dup(comm,&plan->comm);
|
||||
|
||||
// return pointer to plan
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Destroy a 3d remap plan
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void remap_3d_destroy_plan(struct remap_plan_3d *plan)
|
||||
|
||||
{
|
||||
// free MPI communicator
|
||||
|
||||
MPI_Comm_free(&plan->comm);
|
||||
|
||||
// free internal arrays
|
||||
|
||||
if (plan->nsend || plan->self) {
|
||||
free(plan->send_offset);
|
||||
free(plan->send_size);
|
||||
free(plan->send_proc);
|
||||
free(plan->packplan);
|
||||
if (plan->sendbuf) free(plan->sendbuf);
|
||||
}
|
||||
|
||||
if (plan->nrecv || plan->self) {
|
||||
free(plan->recv_offset);
|
||||
free(plan->recv_size);
|
||||
free(plan->recv_proc);
|
||||
free(plan->recv_bufloc);
|
||||
free(plan->request);
|
||||
free(plan->unpackplan);
|
||||
if (plan->scratch) free(plan->scratch);
|
||||
}
|
||||
|
||||
// free plan itself
|
||||
|
||||
free(plan);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
collide 2 sets of indices to determine overlap
|
||||
compare bounds of block1 with block2 to see if they overlap
|
||||
return 1 if they do and put bounds of overlapping section in overlap
|
||||
return 0 if they do not overlap
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int remap_3d_collide(struct extent_3d *block1, struct extent_3d *block2,
|
||||
struct extent_3d *overlap)
|
||||
|
||||
{
|
||||
overlap->ilo = MAX(block1->ilo,block2->ilo);
|
||||
overlap->ihi = MIN(block1->ihi,block2->ihi);
|
||||
overlap->jlo = MAX(block1->jlo,block2->jlo);
|
||||
overlap->jhi = MIN(block1->jhi,block2->jhi);
|
||||
overlap->klo = MAX(block1->klo,block2->klo);
|
||||
overlap->khi = MIN(block1->khi,block2->khi);
|
||||
|
||||
if (overlap->ilo > overlap->ihi ||
|
||||
overlap->jlo > overlap->jhi ||
|
||||
overlap->klo > overlap->khi) return 0;
|
||||
|
||||
overlap->isize = overlap->ihi - overlap->ilo + 1;
|
||||
overlap->jsize = overlap->jhi - overlap->jlo + 1;
|
||||
overlap->ksize = overlap->khi - overlap->klo + 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
56
src/remap.h
56
src/remap.h
@ -1,56 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
// details of how to do a 3d remap
|
||||
|
||||
struct remap_plan_3d {
|
||||
double *sendbuf; // buffer for MPI sends
|
||||
double *scratch; // scratch buffer for MPI recvs
|
||||
void (*pack)(double *, double *, struct pack_plan_3d *);
|
||||
// which pack function to use
|
||||
void (*unpack)(double *, double *, struct pack_plan_3d *);
|
||||
// which unpack function to use
|
||||
int *send_offset; // extraction loc for each send
|
||||
int *send_size; // size of each send message
|
||||
int *send_proc; // proc to send each message to
|
||||
struct pack_plan_3d *packplan; // pack plan for each send message
|
||||
int *recv_offset; // insertion loc for each recv
|
||||
int *recv_size; // size of each recv message
|
||||
int *recv_proc; // proc to recv each message from
|
||||
int *recv_bufloc; // offset in scratch buf for each recv
|
||||
MPI_Request *request; // MPI request for each posted recv
|
||||
struct pack_plan_3d *unpackplan; // unpack plan for each recv message
|
||||
int nrecv; // # of recvs from other procs
|
||||
int nsend; // # of sends to other procs
|
||||
int self; // whether I send/recv with myself
|
||||
int memory; // user provides scratch space or not
|
||||
MPI_Comm comm; // group of procs performing remap
|
||||
};
|
||||
|
||||
// collision between 2 regions
|
||||
|
||||
struct extent_3d {
|
||||
int ilo,ihi,isize;
|
||||
int jlo,jhi,jsize;
|
||||
int klo,khi,ksize;
|
||||
};
|
||||
|
||||
// function prototypes
|
||||
|
||||
void remap_3d(double *, double *, double *, struct remap_plan_3d *);
|
||||
struct remap_plan_3d *remap_3d_create_plan(MPI_Comm,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int);
|
||||
void remap_3d_destroy_plan(struct remap_plan_3d *);
|
||||
int remap_3d_collide(struct extent_3d *,
|
||||
struct extent_3d *, struct extent_3d *);
|
||||
@ -1,46 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "remap_wrap.h"
|
||||
#include "error.h"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Remap::Remap(MPI_Comm comm,
|
||||
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
|
||||
int in_klo, int in_khi,
|
||||
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
|
||||
int out_klo, int out_khi,
|
||||
int nqty, int permute, int memory, int precision)
|
||||
{
|
||||
plan = remap_3d_create_plan(comm,
|
||||
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
|
||||
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
|
||||
nqty,permute,memory,precision);
|
||||
if (plan == NULL) error->one("Could not create 3d remap plan");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Remap::~Remap()
|
||||
{
|
||||
remap_3d_destroy_plan(plan);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Remap::perform(double *in, double *out, double *buf)
|
||||
{
|
||||
remap_3d(in,out,buf,plan);
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef REMAP_WRAP_H
|
||||
#define REMAP_WRAP_H
|
||||
|
||||
#include "lammps.h"
|
||||
#include "remap.h"
|
||||
|
||||
class Remap : public LAMMPS {
|
||||
public:
|
||||
Remap(MPI_Comm,int,int,int,int,int,int,
|
||||
int,int,int,int,int,int,int,int,int,int);
|
||||
~Remap();
|
||||
void perform(double *, double *, double *);
|
||||
|
||||
private:
|
||||
struct remap_plan_3d *plan;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,38 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef KSpaceInclude
|
||||
#include "ewald.h"
|
||||
#include "pppm.h"
|
||||
#include "pppm_tip4p.h"
|
||||
#endif
|
||||
|
||||
#ifdef KSpaceClass
|
||||
KSpaceStyle(ewald,Ewald)
|
||||
KSpaceStyle(pppm,PPPM)
|
||||
KSpaceStyle(pppm/tip4p,PPPMTIP4P)
|
||||
#endif
|
||||
|
||||
#ifdef PairInclude
|
||||
#include "pair_buck_coul_long.h"
|
||||
#include "pair_lj_cut_coul_long.h"
|
||||
#include "pair_lj_cut_coul_long_tip4p.h"
|
||||
#include "pair_lj_charmm_coul_long.h"
|
||||
#endif
|
||||
|
||||
#ifdef PairClass
|
||||
PairStyle(buck/coul/long,PairBuckCoulLong)
|
||||
PairStyle(lj/cut/coul/long,PairLJCutCoulLong)
|
||||
PairStyle(lj/cut/coul/long/tip4p,PairLJCutCoulLongTIP4P)
|
||||
PairStyle(lj/charmm/coul/long,PairLJCharmmCoulLong)
|
||||
#endif
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PairInclude
|
||||
#include "pair_eam.h"
|
||||
#include "pair_eam_alloy.h"
|
||||
#include "pair_eam_fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef PairClass
|
||||
PairStyle(eam,PairEAM)
|
||||
PairStyle(eam/alloy,PairEAMAlloy)
|
||||
PairStyle(eam/fs,PairEAMFS)
|
||||
#endif
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
www.cs.sandia.gov/~sjplimp/lammps.html
|
||||
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
|
||||
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef AngleInclude
|
||||
#include "angle_charmm.h"
|
||||
#include "angle_cosine.h"
|
||||
#include "angle_cosine_squared.h"
|
||||
#include "angle_harmonic.h"
|
||||
#include "angle_hybrid.h"
|
||||
#endif
|
||||
|
||||
#ifdef AngleClass
|
||||
AngleStyle(charmm,AngleCharmm)
|
||||
AngleStyle(cosine,AngleCosine)
|
||||
AngleStyle(cosine/squared,AngleCosineSquared)
|
||||
AngleStyle(harmonic,AngleHarmonic)
|
||||
AngleStyle(hybrid,AngleHybrid)
|
||||
#endif
|
||||
|
||||
#ifdef AtomInclude
|
||||
#include "atom_angle.h"
|
||||
#include "atom_bond.h"
|
||||
#include "atom_full.h"
|
||||
#include "atom_molecular.h"
|
||||
#endif
|
||||
|
||||
#ifdef AtomClass
|
||||
AtomStyle(angle,AtomAngle)
|
||||
AtomStyle(bond,AtomBond)
|
||||
AtomStyle(full,AtomFull)
|
||||
AtomStyle(molecular,AtomMolecular)
|
||||
#endif
|
||||
|
||||
#ifdef BondInclude
|
||||
#include "bond_fene.h"
|
||||
#include "bond_fene_expand.h"
|
||||
#include "bond_harmonic.h"
|
||||
#include "bond_hybrid.h"
|
||||
#include "bond_morse.h"
|
||||
#include "bond_nonlinear.h"
|
||||
#include "bond_quartic.h"
|
||||
#endif
|
||||
|
||||
#ifdef BondClass
|
||||
BondStyle(fene,BondFENE)
|
||||
BondStyle(fene/expand,BondFENEExpand)
|
||||
BondStyle(harmonic,BondHarmonic)
|
||||
BondStyle(hybrid,BondHybrid)
|
||||
BondStyle(morse,BondMorse)
|
||||
BondStyle(nonlinear,BondNonlinear)
|
||||
BondStyle(quartic,BondQuartic)
|
||||
#endif
|
||||
|
||||
#ifdef DihedralInclude
|
||||
#include "dihedral_charmm.h"
|
||||
#include "dihedral_harmonic.h"
|
||||
#include "dihedral_helix.h"
|
||||
#include "dihedral_hybrid.h"
|
||||
#include "dihedral_multi_harmonic.h"
|
||||
#include "dihedral_opls.h"
|
||||
#endif
|
||||
|
||||
#ifdef DihedralClass
|
||||
DihedralStyle(charmm,DihedralCharmm)
|
||||
DihedralStyle(harmonic,DihedralHarmonic)
|
||||
DihedralStyle(helix,DihedralHelix)
|
||||
DihedralStyle(hybrid,DihedralHybrid)
|
||||
DihedralStyle(multi/harmonic,DihedralMultiHarmonic)
|
||||
DihedralStyle(opls,DihedralOPLS)
|
||||
#endif
|
||||
|
||||
#ifdef DumpInclude
|
||||
#include "dump_bond.h"
|
||||
#endif
|
||||
|
||||
#ifdef DumpClass
|
||||
DumpStyle(bond,DumpBond)
|
||||
#endif
|
||||
|
||||
#ifdef FixInclude
|
||||
#endif
|
||||
|
||||
#ifdef FixClass
|
||||
#endif
|
||||
|
||||
#ifdef ImproperInclude
|
||||
#include "improper_cvff.h"
|
||||
#include "improper_harmonic.h"
|
||||
#include "improper_hybrid.h"
|
||||
#endif
|
||||
|
||||
#ifdef ImproperClass
|
||||
ImproperStyle(cvff,ImproperCvff)
|
||||
ImproperStyle(harmonic,ImproperHarmonic)
|
||||
ImproperStyle(hybrid,ImproperHybrid)
|
||||
#endif
|
||||
|
||||
#ifdef PairInclude
|
||||
#include "pair_lj_charmm_coul_charmm.h"
|
||||
#include "pair_lj_charmm_coul_charmm_implicit.h"
|
||||
#endif
|
||||
|
||||
#ifdef PairClass
|
||||
PairStyle(lj/charmm/coul/charmm,PairLJCharmmCoulCharmm)
|
||||
PairStyle(lj/charmm/coul/charmm/implicit,PairLJCharmmCoulCharmmImplicit)
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user