git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@64 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2006-10-03 17:52:58 +00:00
parent b2c1d705e2
commit 1a55f94e8a
91 changed files with 9 additions and 20299 deletions

View File

@ -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"

View File

@ -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");
}

View File

@ -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));
}

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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]);
}
}

View File

@ -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

View File

@ -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]);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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
}

View File

@ -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 *);

View File

@ -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);
}

View File

@ -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

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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];
}
}
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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