git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9013 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
@ -10,12 +10,19 @@ if (test $1 = 1) then
|
|||||||
cp angle_cosine_shift.cpp ..
|
cp angle_cosine_shift.cpp ..
|
||||||
cp angle_cosine_shift_exp.cpp ..
|
cp angle_cosine_shift_exp.cpp ..
|
||||||
cp angle_dipole.cpp ..
|
cp angle_dipole.cpp ..
|
||||||
|
cp angle_fourier.cpp ..
|
||||||
|
cp angle_fourier_simple.cpp ..
|
||||||
|
cp angle_quartic.cpp ..
|
||||||
cp bond_harmonic_shift.cpp ..
|
cp bond_harmonic_shift.cpp ..
|
||||||
cp bond_harmonic_shift_cut.cpp ..
|
cp bond_harmonic_shift_cut.cpp ..
|
||||||
cp compute_ackland_atom.cpp ..
|
cp compute_ackland_atom.cpp ..
|
||||||
cp compute_temp_rotate.cpp ..
|
cp compute_temp_rotate.cpp ..
|
||||||
cp dihedral_cosine_shift_exp.cpp ..
|
cp dihedral_cosine_shift_exp.cpp ..
|
||||||
|
cp dihedral_fourier.cpp ..
|
||||||
|
cp dihedral_nharmonic.cpp ..
|
||||||
|
cp dihedral_quadratic.cpp ..
|
||||||
cp dihedral_table.cpp ..
|
cp dihedral_table.cpp ..
|
||||||
|
cp improper_fourier.cpp ..
|
||||||
cp fix_addtorque.cpp ..
|
cp fix_addtorque.cpp ..
|
||||||
cp fix_imd.cpp ..
|
cp fix_imd.cpp ..
|
||||||
cp fix_smd.cpp ..
|
cp fix_smd.cpp ..
|
||||||
@ -32,12 +39,19 @@ if (test $1 = 1) then
|
|||||||
cp angle_cosine_shift.h ..
|
cp angle_cosine_shift.h ..
|
||||||
cp angle_cosine_shift_exp.h ..
|
cp angle_cosine_shift_exp.h ..
|
||||||
cp angle_dipole.h ..
|
cp angle_dipole.h ..
|
||||||
|
cp angle_fourier.h ..
|
||||||
|
cp angle_fourier_simple.h ..
|
||||||
|
cp angle_quartic.h ..
|
||||||
cp bond_harmonic_shift.h ..
|
cp bond_harmonic_shift.h ..
|
||||||
cp bond_harmonic_shift_cut.h ..
|
cp bond_harmonic_shift_cut.h ..
|
||||||
cp compute_ackland_atom.h ..
|
cp compute_ackland_atom.h ..
|
||||||
cp compute_temp_rotate.h ..
|
cp compute_temp_rotate.h ..
|
||||||
cp dihedral_cosine_shift_exp.h ..
|
cp dihedral_cosine_shift_exp.h ..
|
||||||
|
cp dihedral_fourier.h ..
|
||||||
|
cp dihedral_nharmonic.h ..
|
||||||
|
cp dihedral_quadratic.h ..
|
||||||
cp dihedral_table.h ..
|
cp dihedral_table.h ..
|
||||||
|
cp improper_fourier.h ..
|
||||||
cp fix_addtorque.h ..
|
cp fix_addtorque.h ..
|
||||||
cp fix_imd.h ..
|
cp fix_imd.h ..
|
||||||
cp fix_smd.h ..
|
cp fix_smd.h ..
|
||||||
@ -55,13 +69,20 @@ elif (test $1 = 0) then
|
|||||||
|
|
||||||
rm -f ../angle_cosine_shift.cpp
|
rm -f ../angle_cosine_shift.cpp
|
||||||
rm -f ../angle_cosine_shift_exp.cpp
|
rm -f ../angle_cosine_shift_exp.cpp
|
||||||
|
rm -f ../angle_fourier.cpp
|
||||||
|
rm -f ../angle_fourier_simple.cpp
|
||||||
rm -f ../angle_dipole.cpp
|
rm -f ../angle_dipole.cpp
|
||||||
|
rm -f ../angle_quartic.cpp
|
||||||
rm -f ../bond_harmonic_shift.cpp
|
rm -f ../bond_harmonic_shift.cpp
|
||||||
rm -f ../bond_harmonic_shift_cut.cpp
|
rm -f ../bond_harmonic_shift_cut.cpp
|
||||||
rm -f ../compute_ackland_atom.cpp
|
rm -f ../compute_ackland_atom.cpp
|
||||||
rm -f ../compute_temp_rotate.cpp
|
rm -f ../compute_temp_rotate.cpp
|
||||||
rm -f ../dihedral_cosine_shift_exp.cpp
|
rm -f ../dihedral_cosine_shift_exp.cpp
|
||||||
|
rm -f ../dihedral_fourier.cpp
|
||||||
|
rm -f ../dihedral_nharmonic.cpp
|
||||||
|
rm -f ../dihedral_quadratic.cpp
|
||||||
rm -f ../dihedral_table.cpp
|
rm -f ../dihedral_table.cpp
|
||||||
|
rm -f ../improper_fourier.cpp
|
||||||
rm -f ../fix_addtorque.cpp
|
rm -f ../fix_addtorque.cpp
|
||||||
rm -f ../fix_imd.cpp
|
rm -f ../fix_imd.cpp
|
||||||
rm -f ../fix_smd.cpp
|
rm -f ../fix_smd.cpp
|
||||||
@ -79,12 +100,19 @@ elif (test $1 = 0) then
|
|||||||
rm -f ../angle_cosine_shift.h
|
rm -f ../angle_cosine_shift.h
|
||||||
rm -f ../angle_cosine_shift_exp.h
|
rm -f ../angle_cosine_shift_exp.h
|
||||||
rm -f ../angle_dipole.h
|
rm -f ../angle_dipole.h
|
||||||
|
rm -f ../angle_fourier.h
|
||||||
|
rm -f ../angle_fourier_simple.h
|
||||||
|
rm -f ../angle_quartic.h
|
||||||
rm -f ../bond_harmonic_shift.h
|
rm -f ../bond_harmonic_shift.h
|
||||||
rm -f ../bond_harmonic_shift_cut.h
|
rm -f ../bond_harmonic_shift_cut.h
|
||||||
rm -f ../compute_ackland_atom.h
|
rm -f ../compute_ackland_atom.h
|
||||||
rm -f ../compute_temp_rotate.h
|
rm -f ../compute_temp_rotate.h
|
||||||
rm -f ../dihedral_cosine_shift_exp.h
|
rm -f ../dihedral_cosine_shift_exp.h
|
||||||
|
rm -f ../dihedral_fourier.h
|
||||||
|
rm -f ../dihedral_nharmonic.h
|
||||||
|
rm -f ../dihedral_quadratic.h
|
||||||
rm -f ../dihedral_table.h
|
rm -f ../dihedral_table.h
|
||||||
|
rm -f ../improper_fourier.h
|
||||||
rm -f ../fix_addtorque.h
|
rm -f ../fix_addtorque.h
|
||||||
rm -f ../fix_imd.h
|
rm -f ../fix_imd.h
|
||||||
rm -f ../fix_smd.h
|
rm -f ../fix_smd.h
|
||||||
|
|||||||
268
src/USER-MISC/angle_fourier.cpp
Normal file
268
src/USER-MISC/angle_fourier.cpp
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on angle_cosine_squared.cpp Naveen Michaud-Agrawal (Johns Hopkins U)]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "angle_fourier.h"
|
||||||
|
#include "atom.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "domain.h"
|
||||||
|
#include "comm.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "math_const.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
using namespace MathConst;
|
||||||
|
|
||||||
|
#define SMALL 0.001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleFourier::AngleFourier(LAMMPS *lmp) : Angle(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleFourier::~AngleFourier()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(k);
|
||||||
|
memory->destroy(C0);
|
||||||
|
memory->destroy(C1);
|
||||||
|
memory->destroy(C2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourier::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,n,type;
|
||||||
|
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||||
|
double eangle,f1[3],f3[3];
|
||||||
|
double term;
|
||||||
|
double rsq1,rsq2,r1,r2,c,c2,a,a11,a12,a22;
|
||||||
|
|
||||||
|
eangle = 0.0;
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 1st bond
|
||||||
|
|
||||||
|
delx1 = x[i1][0] - x[i2][0];
|
||||||
|
dely1 = x[i1][1] - x[i2][1];
|
||||||
|
delz1 = x[i1][2] - x[i2][2];
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
c2 = 2.0*c*c-1.0;
|
||||||
|
term = k[type]*(C0[type]+C1[type]*c+C2[type]*c2);
|
||||||
|
|
||||||
|
if (eflag) eangle = term;
|
||||||
|
|
||||||
|
a = k[type]*(C1[type]+4.0*C2[type]*c);
|
||||||
|
a11 = a*c / rsq1;
|
||||||
|
a12 = -a / (r1*r2);
|
||||||
|
a22 = a*c / rsq2;
|
||||||
|
|
||||||
|
f1[0] = a11*delx1 + a12*delx2;
|
||||||
|
f1[1] = a11*dely1 + a12*dely2;
|
||||||
|
f1[2] = a11*delz1 + a12*delz2;
|
||||||
|
f3[0] = a22*delx2 + a12*delx1;
|
||||||
|
f3[1] = a22*dely2 + a12*dely1;
|
||||||
|
f3[2] = a22*delz2 + a12*delz1;
|
||||||
|
|
||||||
|
// apply force to each of 3 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] -= f1[0] + f3[0];
|
||||||
|
f[i2][1] -= f1[1] + f3[1];
|
||||||
|
f[i2][2] -= f1[2] + f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
|
||||||
|
delx1,dely1,delz1,delx2,dely2,delz2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourier::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->nangletypes;
|
||||||
|
|
||||||
|
memory->create(k,n+1,"angle:k");
|
||||||
|
memory->create(C0,n+1,"angle:C0");
|
||||||
|
memory->create(C1,n+1,"angle:C1");
|
||||||
|
memory->create(C2,n+1,"angle:C2");
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"angle:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one or more types
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourier::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg != 5) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||||
|
|
||||||
|
double k_one = force->numeric(arg[1]);
|
||||||
|
double C0_one = force->numeric(arg[2]);
|
||||||
|
double C1_one = force->numeric(arg[3]);
|
||||||
|
double C2_one = force->numeric(arg[4]);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
k[i] = k_one;
|
||||||
|
C0[i] = C0_one;
|
||||||
|
C1[i] = C1_one;
|
||||||
|
C2[i] = C2_one;
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double AngleFourier::equilibrium_angle(int i)
|
||||||
|
{
|
||||||
|
double ret=MY_PI;
|
||||||
|
if ( C2[i] != 0.0 ) {
|
||||||
|
ret = (C1[i]/4.0/C2[i]);
|
||||||
|
if ( abs(ret) <= 1.0 ) ret = acos(-ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourier::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&C0[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&C1[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&C2[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourier::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&C0[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&C1[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&C2[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C0[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C1[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C2[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double AngleFourier::single(int type, int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
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 c2 = 2.0*c*c-1.0;
|
||||||
|
|
||||||
|
double eng = k[type]*(C0[type]+C1[type]*c+C2[type]*c2);
|
||||||
|
return eng;
|
||||||
|
}
|
||||||
48
src/USER-MISC/angle_fourier.h
Normal file
48
src/USER-MISC/angle_fourier.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef ANGLE_CLASS
|
||||||
|
|
||||||
|
AngleStyle(fourier,AngleFourier)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef ANGLE_FOURIER_H
|
||||||
|
#define ANGLE_FOURIER_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "angle.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class AngleFourier : public Angle {
|
||||||
|
public:
|
||||||
|
AngleFourier(class LAMMPS *);
|
||||||
|
virtual ~AngleFourier();
|
||||||
|
virtual void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
double equilibrium_angle(int);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
virtual double single(int, int, int, int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *k,*C0,*C1,*C2;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
274
src/USER-MISC/angle_fourier_simple.cpp
Normal file
274
src/USER-MISC/angle_fourier_simple.cpp
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on angle_cosine_quared.cpp Naveen Michaud-Agrawal (Johns Hopkins U)]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "angle_fourier_simple.h"
|
||||||
|
#include "atom.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "domain.h"
|
||||||
|
#include "comm.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "math_const.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
using namespace MathConst;
|
||||||
|
|
||||||
|
#define SMALL 0.001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleFourierSimple::AngleFourierSimple(LAMMPS *lmp) : Angle(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleFourierSimple::~AngleFourierSimple()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(k);
|
||||||
|
memory->destroy(C);
|
||||||
|
memory->destroy(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourierSimple::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,n,type;
|
||||||
|
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||||
|
double eangle,f1[3],f3[3];
|
||||||
|
double term,sgn;
|
||||||
|
double rsq1,rsq2,r1,r2,c,cn,th,nth,a,a11,a12,a22;
|
||||||
|
|
||||||
|
eangle = 0.0;
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 1st bond
|
||||||
|
|
||||||
|
delx1 = x[i1][0] - x[i2][0];
|
||||||
|
dely1 = x[i1][1] - x[i2][1];
|
||||||
|
delz1 = x[i1][2] - x[i2][2];
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
th = acos(c);
|
||||||
|
nth = N[type]*acos(c);
|
||||||
|
cn = cos(nth);
|
||||||
|
term = k[type]*(1.0+C[type]*cn);
|
||||||
|
|
||||||
|
if (eflag) eangle = term;
|
||||||
|
|
||||||
|
// handle sin(n th)/sin(th) singulatiries
|
||||||
|
|
||||||
|
if ( abs(c)-1.0 > 0.0001 )
|
||||||
|
{
|
||||||
|
a = k[type]*C[type]*N[type]*sin(nth)/sin(th);
|
||||||
|
} else {
|
||||||
|
if ( c >= 0.0 ) {
|
||||||
|
term = 1.0 - c;
|
||||||
|
sgn = 1.0;
|
||||||
|
} else {
|
||||||
|
term = 1.0 + c;
|
||||||
|
sgn = ( fmodf((float)(N[type]),2.0) == 0.0f )?-1.0:1.0;
|
||||||
|
}
|
||||||
|
a = N[type]+N[type]*(1.0-N[type]*N[type])*term/3.0;
|
||||||
|
a = k[type]*C[type]*N[type]*(double)(sgn)*a;
|
||||||
|
}
|
||||||
|
|
||||||
|
a11 = a*c / rsq1;
|
||||||
|
a12 = -a / (r1*r2);
|
||||||
|
a22 = a*c / rsq2;
|
||||||
|
|
||||||
|
f1[0] = a11*delx1 + a12*delx2;
|
||||||
|
f1[1] = a11*dely1 + a12*dely2;
|
||||||
|
f1[2] = a11*delz1 + a12*delz2;
|
||||||
|
f3[0] = a22*delx2 + a12*delx1;
|
||||||
|
f3[1] = a22*dely2 + a12*dely1;
|
||||||
|
f3[2] = a22*delz2 + a12*delz1;
|
||||||
|
|
||||||
|
// apply force to each of 3 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] -= f1[0] + f3[0];
|
||||||
|
f[i2][1] -= f1[1] + f3[1];
|
||||||
|
f[i2][2] -= f1[2] + f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
|
||||||
|
delx1,dely1,delz1,delx2,dely2,delz2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourierSimple::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->nangletypes;
|
||||||
|
|
||||||
|
memory->create(k,n+1,"angle:k");
|
||||||
|
memory->create(C,n+1,"angle:C");
|
||||||
|
memory->create(N,n+1,"angle:N");
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"angle:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one or more types
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourierSimple::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg != 4) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||||
|
|
||||||
|
double k_one = force->numeric(arg[1]);
|
||||||
|
double C_one = force->numeric(arg[2]);
|
||||||
|
double N_one = force->numeric(arg[3]);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
k[i] = k_one;
|
||||||
|
C[i] = C_one;
|
||||||
|
N[i] = N_one;
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double AngleFourierSimple::equilibrium_angle(int i)
|
||||||
|
{
|
||||||
|
return (MY_PI/N[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourierSimple::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&C[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&N[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleFourierSimple::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
fread(&k[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&C[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&N[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&N[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double AngleFourierSimple::single(int type, int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
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 cn = cos(N[type]*acos(c));
|
||||||
|
|
||||||
|
double eng = k[type]*(1.0+C[type]*cn);
|
||||||
|
return eng;
|
||||||
|
}
|
||||||
48
src/USER-MISC/angle_fourier_simple.h
Normal file
48
src/USER-MISC/angle_fourier_simple.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef ANGLE_CLASS
|
||||||
|
|
||||||
|
AngleStyle(fourier/simple,AngleFourierSimple)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef ANGLE_FOURIER_SIMPLE_H
|
||||||
|
#define ANGLE_FOURIER_SIMPLE_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "angle.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class AngleFourierSimple : public Angle {
|
||||||
|
public:
|
||||||
|
AngleFourierSimple(class LAMMPS *);
|
||||||
|
virtual ~AngleFourierSimple();
|
||||||
|
virtual void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
double equilibrium_angle(int);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
virtual double single(int, int, int, int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *k,*C,*N;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
277
src/USER-MISC/angle_quartic.cpp
Normal file
277
src/USER-MISC/angle_quartic.cpp
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on angle_harmonic.cpp]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "angle_quartic.h"
|
||||||
|
#include "atom.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "domain.h"
|
||||||
|
#include "comm.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "math_const.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
using namespace MathConst;
|
||||||
|
|
||||||
|
#define SMALL 0.001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleQuartic::AngleQuartic(LAMMPS *lmp) : Angle(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
AngleQuartic::~AngleQuartic()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(k2);
|
||||||
|
memory->destroy(k3);
|
||||||
|
memory->destroy(k4);
|
||||||
|
memory->destroy(theta0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleQuartic::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,n,type;
|
||||||
|
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||||
|
double eangle,f1[3],f3[3];
|
||||||
|
double dtheta,dtheta2,dtheta3,dtheta4,tk;
|
||||||
|
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
|
||||||
|
|
||||||
|
eangle = 0.0;
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 1st bond
|
||||||
|
|
||||||
|
delx1 = x[i1][0] - x[i2][0];
|
||||||
|
dely1 = x[i1][1] - x[i2][1];
|
||||||
|
delz1 = x[i1][2] - x[i2][2];
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
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];
|
||||||
|
dtheta2 = dtheta * dtheta;
|
||||||
|
dtheta3 = dtheta2 * dtheta;
|
||||||
|
tk = 2.0 * k2[type] * dtheta + 3.0 * k3[type] * dtheta2 + 4.0 * k4[type] * dtheta3;
|
||||||
|
|
||||||
|
if (eflag) {
|
||||||
|
dtheta4 = dtheta3 * dtheta;
|
||||||
|
eangle = k2[type] * dtheta2 + k3[type] * dtheta3 + k4[type] * dtheta4;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = -2.0 * tk * s;
|
||||||
|
a11 = a*c / rsq1;
|
||||||
|
a12 = -a / (r1*r2);
|
||||||
|
a22 = a*c / rsq2;
|
||||||
|
|
||||||
|
f1[0] = a11*delx1 + a12*delx2;
|
||||||
|
f1[1] = a11*dely1 + a12*dely2;
|
||||||
|
f1[2] = a11*delz1 + a12*delz2;
|
||||||
|
f3[0] = a22*delx2 + a12*delx1;
|
||||||
|
f3[1] = a22*dely2 + a12*dely1;
|
||||||
|
f3[2] = a22*delz2 + a12*delz1;
|
||||||
|
|
||||||
|
// apply force to each of 3 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] -= f1[0] + f3[0];
|
||||||
|
f[i2][1] -= f1[1] + f3[1];
|
||||||
|
f[i2][2] -= f1[2] + f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
|
||||||
|
delx1,dely1,delz1,delx2,dely2,delz2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleQuartic::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->nangletypes;
|
||||||
|
|
||||||
|
memory->create(k2,n+1,"angle:k2");
|
||||||
|
memory->create(k3,n+1,"angle:k3");
|
||||||
|
memory->create(k4,n+1,"angle:k4");
|
||||||
|
memory->create(theta0,n+1,"angle:theta0");
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"angle:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one or more types
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleQuartic::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg != 5) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
|
||||||
|
|
||||||
|
double theta0_one = force->numeric(arg[1]);
|
||||||
|
double k2_one = force->numeric(arg[2]);
|
||||||
|
double k3_one = force->numeric(arg[3]);
|
||||||
|
double k4_one = force->numeric(arg[4]);
|
||||||
|
|
||||||
|
// convert theta0 from degrees to radians
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
k2[i] = k2_one;
|
||||||
|
k3[i] = k3_one;
|
||||||
|
k4[i] = k4_one;
|
||||||
|
theta0[i] = theta0_one/180.0 * MY_PI;
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double AngleQuartic::equilibrium_angle(int i)
|
||||||
|
{
|
||||||
|
return theta0[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleQuartic::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&k2[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&k3[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&k4[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void AngleQuartic::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
fread(&k2[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&k3[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&k4[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
|
||||||
|
}
|
||||||
|
MPI_Bcast(&k2[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&k3[1],atom->nangletypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&k4[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 AngleQuartic::single(int type, int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
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 dtheta2 = dtheta * dtheta;
|
||||||
|
double dtheta3 = dtheta2 * dtheta;
|
||||||
|
double dtheta4 = dtheta3 * dtheta;
|
||||||
|
double tk = 2.0 * k2[type] * dtheta + 3.0 * k3[type] * dtheta2 + 4.0 * k4[type] * dtheta3;
|
||||||
|
return k2[type] * dtheta2 + k3[type] * dtheta3 + k4[type] * dtheta4;
|
||||||
|
}
|
||||||
48
src/USER-MISC/angle_quartic.h
Normal file
48
src/USER-MISC/angle_quartic.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef ANGLE_CLASS
|
||||||
|
|
||||||
|
AngleStyle(quartic,AngleQuartic)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_ANGLE_QUARTIC_H
|
||||||
|
#define LMP_ANGLE_QUARTIC_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "angle.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class AngleQuartic : public Angle {
|
||||||
|
public:
|
||||||
|
AngleQuartic(class LAMMPS *);
|
||||||
|
virtual ~AngleQuartic();
|
||||||
|
virtual void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
double equilibrium_angle(int);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
double single(int, int, int, int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *k2, *k3, *k4, *theta0;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
411
src/USER-MISC/dihedral_fourier.cpp
Normal file
411
src/USER-MISC/dihedral_fourier.cpp
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on dihedral_charmm.cpp Paul Crozier (SNL) ]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "lmptype.h"
|
||||||
|
#include "mpi.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "dihedral_fourier.h"
|
||||||
|
#include "atom.h"
|
||||||
|
#include "comm.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "domain.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "pair.h"
|
||||||
|
#include "update.h"
|
||||||
|
#include "math_const.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
using namespace MathConst;
|
||||||
|
|
||||||
|
#define TOLERANCE 0.05
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralFourier::DihedralFourier(LAMMPS *lmp) : Dihedral(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralFourier::~DihedralFourier()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(nterms);
|
||||||
|
|
||||||
|
for (int i=1; i<= atom->ndihedraltypes; i++) {
|
||||||
|
if ( k[i] ) delete [] k[i];
|
||||||
|
if ( multiplicity[i] ) delete [] multiplicity[i];
|
||||||
|
if ( shift[i] ) delete [] shift[i];
|
||||||
|
if ( cos_shift[i] ) delete [] cos_shift[i];
|
||||||
|
if ( sin_shift[i] ) delete [] sin_shift[i];
|
||||||
|
}
|
||||||
|
delete [] k;
|
||||||
|
delete [] multiplicity;
|
||||||
|
delete [] shift;
|
||||||
|
delete [] cos_shift;
|
||||||
|
delete [] sin_shift;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralFourier::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,i4,i,j,m,n,type;
|
||||||
|
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||||
|
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||||
|
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,p_,sx2,sy2,sz2;
|
||||||
|
int itype,jtype;
|
||||||
|
double delx,dely,delz,rsq,r2inv,r6inv;
|
||||||
|
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
char str[128];
|
||||||
|
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
|
||||||
|
me,update->ntimestep,
|
||||||
|
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||||
|
error->warning(FLERR,str,0);
|
||||||
|
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 and energy
|
||||||
|
// p = sum(i=1,nterms) k_i*(1+cos(n_i*phi-d_i)
|
||||||
|
// dp = dp / dphi
|
||||||
|
edihedral = 0.0;
|
||||||
|
df = 0.0;
|
||||||
|
for (j=0; j<nterms[type]; j++)
|
||||||
|
{
|
||||||
|
m = multiplicity[type][j];
|
||||||
|
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][j] + df1_*sin_shift[type][j];
|
||||||
|
df1_ = df1_*cos_shift[type][j] - ddf1_*sin_shift[type][j];
|
||||||
|
df1_ *= -m;
|
||||||
|
p_ += 1.0;
|
||||||
|
|
||||||
|
if (m == 0) {
|
||||||
|
p_ = 1.0 + cos_shift[type][j];
|
||||||
|
df1_ = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eflag) edihedral += k[type][j] * p_;
|
||||||
|
|
||||||
|
df += (-k[type][j] * df1_);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
sx2 = df*dtgx;
|
||||||
|
sy2 = df*dtgy;
|
||||||
|
sz2 = df*dtgz;
|
||||||
|
|
||||||
|
f1[0] = df*dtfx;
|
||||||
|
f1[1] = df*dtfy;
|
||||||
|
f1[2] = df*dtfz;
|
||||||
|
|
||||||
|
f2[0] = sx2 - f1[0];
|
||||||
|
f2[1] = sy2 - f1[1];
|
||||||
|
f2[2] = sz2 - f1[2];
|
||||||
|
|
||||||
|
f4[0] = df*dthx;
|
||||||
|
f4[1] = df*dthy;
|
||||||
|
f4[2] = df*dthz;
|
||||||
|
|
||||||
|
f3[0] = -sx2 - f4[0];
|
||||||
|
f3[1] = -sy2 - f4[1];
|
||||||
|
f3[2] = -sz2 - f4[2];
|
||||||
|
|
||||||
|
// apply force to each of 4 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] += f2[0];
|
||||||
|
f[i2][1] += f2[1];
|
||||||
|
f[i2][2] += f2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i4 < nlocal) {
|
||||||
|
f[i4][0] += f4[0];
|
||||||
|
f[i4][1] += f4[1];
|
||||||
|
f[i4][2] += f4[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag)
|
||||||
|
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
|
||||||
|
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralFourier::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->ndihedraltypes;
|
||||||
|
|
||||||
|
memory->create(nterms,n+1,"dihedral:nterms");
|
||||||
|
k = new double * [n+1];
|
||||||
|
multiplicity = new int * [n+1];
|
||||||
|
shift = new int * [n+1];
|
||||||
|
cos_shift = new double * [n+1];
|
||||||
|
sin_shift = new double * [n+1];
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
k[i] = cos_shift[i] = sin_shift[i] = 0;
|
||||||
|
multiplicity[i] = shift[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"dihedral:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one type
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralFourier::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg < 4) error->all(FLERR,"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;
|
||||||
|
int multiplicity_one;
|
||||||
|
int shift_one;
|
||||||
|
int nterms_one = force->inumeric(arg[1]);
|
||||||
|
|
||||||
|
if (nterms_one < 1)
|
||||||
|
error->all(FLERR,"Incorrect number of terms arg for dihedral coefficients");
|
||||||
|
|
||||||
|
if (2+3*nterms_one < narg)
|
||||||
|
error->all(FLERR,"Incorrect number of arguments for dihedral coefficients");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
nterms[i] = nterms_one;
|
||||||
|
k[i] = new double [nterms_one];
|
||||||
|
multiplicity[i] = new int [nterms_one];
|
||||||
|
shift[i] = new int [nterms_one];
|
||||||
|
cos_shift[i] = new double [nterms_one];
|
||||||
|
sin_shift[i] = new double [nterms_one];
|
||||||
|
for (int j = 0; j<nterms_one; j++) {
|
||||||
|
int offset = 1+3*j;
|
||||||
|
k_one = force->numeric(arg[offset+1]);
|
||||||
|
multiplicity_one = force->inumeric(arg[offset+2]);
|
||||||
|
shift_one = force->inumeric(arg[offset+3]);
|
||||||
|
k[i][j] = k_one;
|
||||||
|
multiplicity[i][j] = multiplicity_one;
|
||||||
|
shift[i][j] = shift_one;
|
||||||
|
cos_shift[i][j] = cos(MY_PI*shift_one/180.0);
|
||||||
|
sin_shift[i][j] = sin(MY_PI*shift_one/180.0);
|
||||||
|
}
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralFourier::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
|
||||||
|
fwrite(&nterms[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||||
|
for(int i = 1; i <= atom->ndihedraltypes; i++) {
|
||||||
|
fwrite(k[i],sizeof(double),nterms[i],fp);
|
||||||
|
fwrite(multiplicity[i],sizeof(int),nterms[i],fp);
|
||||||
|
fwrite(shift[i],sizeof(int),nterms[i],fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralFourier::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0)
|
||||||
|
fread(&nterms[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||||
|
|
||||||
|
MPI_Bcast(&nterms[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||||
|
|
||||||
|
// allocate
|
||||||
|
for (int i=1; i<=atom->ndihedraltypes; i++) {
|
||||||
|
k[i] = new double [nterms[i]];
|
||||||
|
multiplicity[i] = new int [nterms[i]];
|
||||||
|
shift[i] = new int [nterms[i]];
|
||||||
|
cos_shift[i] = new double [nterms[i]];
|
||||||
|
sin_shift[i] = new double [nterms[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
for (int i=1; i<=atom->ndihedraltypes; i++) {
|
||||||
|
fread(k[i],sizeof(double),nterms[i],fp);
|
||||||
|
fread(multiplicity[i],sizeof(int),nterms[i],fp);
|
||||||
|
fread(shift[i],sizeof(int),nterms[i],fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=1; i<=atom->ndihedraltypes; i++) {
|
||||||
|
MPI_Bcast(k[i],nterms[i],MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(multiplicity[i],nterms[i],MPI_INT,0,world);
|
||||||
|
MPI_Bcast(shift[i],nterms[i],MPI_INT,0,world);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=1; i <= atom->ndihedraltypes; i++) {
|
||||||
|
setflag[i] = 1;
|
||||||
|
for (int j = 0; j < nterms[i]; j++) {
|
||||||
|
cos_shift[i][j] = cos(MY_PI*shift[i][j]/180.0);
|
||||||
|
sin_shift[i][j] = sin(MY_PI*shift[i][j]/180.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
49
src/USER-MISC/dihedral_fourier.h
Normal file
49
src/USER-MISC/dihedral_fourier.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef DIHEDRAL_CLASS
|
||||||
|
|
||||||
|
DihedralStyle(fourier,DihedralFourier)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_DIHEDRAL_FOURIER_H
|
||||||
|
#define LMP_DIHEDRAL_FOURIER_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "dihedral.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class DihedralFourier : public Dihedral {
|
||||||
|
public:
|
||||||
|
DihedralFourier(class LAMMPS *);
|
||||||
|
virtual ~DihedralFourier();
|
||||||
|
virtual void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double **k,**cos_shift,**sin_shift;
|
||||||
|
int **multiplicity,**shift;
|
||||||
|
int *nterms;
|
||||||
|
int implicit,weightflag;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
335
src/USER-MISC/dihedral_nharmonic.cpp
Normal file
335
src/USER-MISC/dihedral_nharmonic.cpp
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on dihedral_multi_harmonic.cpp Mathias Puetz (SNL) and friends ]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "lmptype.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "dihedral_nharmonic.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"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
#define TOLERANCE 0.05
|
||||||
|
#define SMALL 0.001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralNHarmonic::DihedralNHarmonic(LAMMPS *lmp) : Dihedral(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralNHarmonic::~DihedralNHarmonic()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
for (int i = 1; i <= atom->ndihedraltypes; i++)
|
||||||
|
delete [] a[i];
|
||||||
|
delete [] a;
|
||||||
|
delete [] nterms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralNHarmonic::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,i4,n,type;
|
||||||
|
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||||
|
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||||
|
double sb1,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,sx2,sy2,sz2;
|
||||||
|
double s2,sin2;
|
||||||
|
|
||||||
|
edihedral = 0.0;
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 1st bond
|
||||||
|
|
||||||
|
vb1x = x[i1][0] - x[i2][0];
|
||||||
|
vb1y = x[i1][1] - x[i2][1];
|
||||||
|
vb1z = x[i1][2] - x[i2][2];
|
||||||
|
|
||||||
|
// 2nd bond
|
||||||
|
|
||||||
|
vb2x = x[i3][0] - x[i2][0];
|
||||||
|
vb2y = x[i3][1] - x[i2][1];
|
||||||
|
vb2z = x[i3][2] - x[i2][2];
|
||||||
|
|
||||||
|
vb2xm = -vb2x;
|
||||||
|
vb2ym = -vb2y;
|
||||||
|
vb2zm = -vb2z;
|
||||||
|
|
||||||
|
// 3rd bond
|
||||||
|
|
||||||
|
vb3x = x[i4][0] - x[i3][0];
|
||||||
|
vb3y = x[i4][1] - x[i3][1];
|
||||||
|
vb3z = x[i4][2] - x[i3][2];
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
int me;
|
||||||
|
MPI_Comm_rank(world,&me);
|
||||||
|
if (screen) {
|
||||||
|
char str[128];
|
||||||
|
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
|
||||||
|
me,update->ntimestep,
|
||||||
|
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||||
|
error->warning(FLERR,str);
|
||||||
|
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 = sum (i=1,n) a_i * c**(i-1)
|
||||||
|
// pd = dp/dc
|
||||||
|
p = this->a[type][0];
|
||||||
|
pd = this->a[type][1];
|
||||||
|
for (int i = 1; i < nterms[type]-1; i++) {
|
||||||
|
p += c * this->a[type][i];
|
||||||
|
pd += c * static_cast<double>(i+1) * this->a[type][i+1];
|
||||||
|
c *= c;
|
||||||
|
}
|
||||||
|
p += c * this->a[type][nterms[type]-1];
|
||||||
|
|
||||||
|
if (eflag) edihedral = 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);
|
||||||
|
|
||||||
|
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||||
|
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||||
|
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||||
|
|
||||||
|
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||||
|
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||||
|
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||||
|
|
||||||
|
f2[0] = -sx2 - f1[0];
|
||||||
|
f2[1] = -sy2 - f1[1];
|
||||||
|
f2[2] = -sz2 - f1[2];
|
||||||
|
|
||||||
|
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||||
|
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||||
|
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||||
|
|
||||||
|
f3[0] = sx2 - f4[0];
|
||||||
|
f3[1] = sy2 - f4[1];
|
||||||
|
f3[2] = sz2 - f4[2];
|
||||||
|
|
||||||
|
// apply force to each of 4 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] += f2[0];
|
||||||
|
f[i2][1] += f2[1];
|
||||||
|
f[i2][2] += f2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i4 < nlocal) {
|
||||||
|
f[i4][0] += f4[0];
|
||||||
|
f[i4][1] += f4[1];
|
||||||
|
f[i4][2] += f4[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag)
|
||||||
|
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
|
||||||
|
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralNHarmonic::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->ndihedraltypes;
|
||||||
|
|
||||||
|
memory->create(nterms,n+1,"dihedral:nt");
|
||||||
|
a = new double * [n+1];
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"dihedral:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one type
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralNHarmonic::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg < 4 ) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
|
||||||
|
int n = force->inumeric(arg[1]);
|
||||||
|
if (narg != n + 2 ) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
a[i] = new double [n];
|
||||||
|
nterms[i] = n;
|
||||||
|
for (int j = 0; j < n; j++ ) {
|
||||||
|
a[i][j] = force->numeric(arg[2+i]);
|
||||||
|
setflag[i] = 1;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralNHarmonic::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&nterms[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||||
|
for(int i = 1; i <= atom->ndihedraltypes; i++)
|
||||||
|
fwrite(a[i],sizeof(double),nterms[i],fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralNHarmonic::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0)
|
||||||
|
fread(&nterms[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||||
|
|
||||||
|
MPI_Bcast(&nterms[1],atom->ndihedraltypes,MPI_INT,0,world);
|
||||||
|
|
||||||
|
// allocate
|
||||||
|
for(int i = 1; i <= atom->ndihedraltypes; i++)
|
||||||
|
a[i] = new double [nterms[i]];
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
for(int i = 1; i <= atom->ndihedraltypes; i++)
|
||||||
|
fread(a[i],sizeof(double),nterms[i],fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->ndihedraltypes; i++ )
|
||||||
|
MPI_Bcast(a[i],nterms[i],MPI_DOUBLE,0,world);
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
47
src/USER-MISC/dihedral_nharmonic.h
Normal file
47
src/USER-MISC/dihedral_nharmonic.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef DIHEDRAL_CLASS
|
||||||
|
|
||||||
|
DihedralStyle(n/harmonic,DihedralNHarmonic)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef DIHEDRAL_NHARMONIC_H
|
||||||
|
#define DIHEDRAL_NHARMONIC_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "dihedral.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class DihedralNHarmonic : public Dihedral {
|
||||||
|
public:
|
||||||
|
DihedralNHarmonic(class LAMMPS *);
|
||||||
|
~DihedralNHarmonic();
|
||||||
|
void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int *nterms;
|
||||||
|
double **a;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
338
src/USER-MISC/dihedral_quadratic.cpp
Normal file
338
src/USER-MISC/dihedral_quadratic.cpp
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on dihedral_helix.cpp Paul Crozier (SNL) ]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "lmptype.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "dihedral_quadratic.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"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
#define TOLERANCE 0.05
|
||||||
|
#define SMALL 0.001
|
||||||
|
#define SMALLER 0.00001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralQuadratic::DihedralQuadratic(LAMMPS *lmp) : Dihedral(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
DihedralQuadratic::~DihedralQuadratic()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(k);
|
||||||
|
memory->destroy(phi0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralQuadratic::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,i4,i,m,n,type;
|
||||||
|
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||||
|
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||||
|
double sb1,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,sx2,sy2,sz2;
|
||||||
|
double s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
|
||||||
|
|
||||||
|
edihedral = 0.0;
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 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];
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
char str[128];
|
||||||
|
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
|
||||||
|
me,update->ntimestep,
|
||||||
|
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||||
|
error->warning(FLERR,str,0);
|
||||||
|
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 = k ( phi- phi0)^2
|
||||||
|
// pd = dp/dc
|
||||||
|
|
||||||
|
phi = acos(c);
|
||||||
|
if (dx < 0.0) phi *= -1.0;
|
||||||
|
si = sin(phi);
|
||||||
|
|
||||||
|
double dphi = phi-phi0[type];
|
||||||
|
p = k[type]*dphi;
|
||||||
|
if (fabs(si) < SMALLER) {
|
||||||
|
pd = - 2.0 * k[type];
|
||||||
|
} else {
|
||||||
|
pd = - 2.0 * p / si;
|
||||||
|
}
|
||||||
|
p = p * dphi;
|
||||||
|
|
||||||
|
if (eflag) edihedral = 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);
|
||||||
|
|
||||||
|
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||||
|
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||||
|
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||||
|
|
||||||
|
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||||
|
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||||
|
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||||
|
|
||||||
|
f2[0] = -sx2 - f1[0];
|
||||||
|
f2[1] = -sy2 - f1[1];
|
||||||
|
f2[2] = -sz2 - f1[2];
|
||||||
|
|
||||||
|
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||||
|
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||||
|
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||||
|
|
||||||
|
f3[0] = sx2 - f4[0];
|
||||||
|
f3[1] = sy2 - f4[1];
|
||||||
|
f3[2] = sz2 - f4[2];
|
||||||
|
|
||||||
|
// apply force to each of 4 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0];
|
||||||
|
f[i1][1] += f1[1];
|
||||||
|
f[i1][2] += f1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] += f2[0];
|
||||||
|
f[i2][1] += f2[1];
|
||||||
|
f[i2][2] += f2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f3[0];
|
||||||
|
f[i3][1] += f3[1];
|
||||||
|
f[i3][2] += f3[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i4 < nlocal) {
|
||||||
|
f[i4][0] += f4[0];
|
||||||
|
f[i4][1] += f4[1];
|
||||||
|
f[i4][2] += f4[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag)
|
||||||
|
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
|
||||||
|
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralQuadratic::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->ndihedraltypes;
|
||||||
|
|
||||||
|
memory->create(k,n+1,"dihedral:k");
|
||||||
|
memory->create(phi0,n+1,"dihedral:phi0");
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"dihedral:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one type
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralQuadratic::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
if (narg != 3) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
|
||||||
|
|
||||||
|
double k_one = force->numeric(arg[1]);
|
||||||
|
double phi0_one= force->numeric(arg[2]);
|
||||||
|
|
||||||
|
// require k >= 0
|
||||||
|
if (k_one < 0.0)
|
||||||
|
error->all(FLERR,"Incorrect coefficient arg for dihedral coefficients");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
k[i] = k_one;
|
||||||
|
phi0[i] = phi0_one;
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralQuadratic::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||||
|
fwrite(&phi0[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void DihedralQuadratic::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
fread(&k[1],sizeof(double),atom->ndihedraltypes,fp);
|
||||||
|
fread(&phi0[1],sizeof(int),atom->ndihedraltypes,fp);
|
||||||
|
}
|
||||||
|
MPI_Bcast(&k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&phi0[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
47
src/USER-MISC/dihedral_quadratic.h
Normal file
47
src/USER-MISC/dihedral_quadratic.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef DIHEDRAL_CLASS
|
||||||
|
|
||||||
|
DihedralStyle(quadratic,DihedralQuadratic)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_DIHEDRAL_QUADRATIC_H
|
||||||
|
#define LMP_DIHEDRAL_QUADRATIC_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "dihedral.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class DihedralQuadratic : public Dihedral {
|
||||||
|
public:
|
||||||
|
DihedralQuadratic(class LAMMPS *);
|
||||||
|
~DihedralQuadratic();
|
||||||
|
void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *k,*phi0;
|
||||||
|
int *sign,*multiplicity;
|
||||||
|
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
344
src/USER-MISC/improper_fourier.cpp
Normal file
344
src/USER-MISC/improper_fourier.cpp
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing author: Loukas D. Peristeras (Scienomics SARL)
|
||||||
|
[ based on improper_umbrella.cpp Tod A Pascal (Caltech) ]
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "mpi.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "improper_fourier.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"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
#define TOLERANCE 0.05
|
||||||
|
#define SMALL 0.001
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ImproperFourier::ImproperFourier(LAMMPS *lmp) : Improper(lmp) {}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ImproperFourier::~ImproperFourier()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
memory->destroy(setflag);
|
||||||
|
memory->destroy(k);
|
||||||
|
memory->destroy(C0);
|
||||||
|
memory->destroy(C1);
|
||||||
|
memory->destroy(C2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ImproperFourier::compute(int eflag, int vflag)
|
||||||
|
{
|
||||||
|
int i1,i2,i3,i4,n,type;
|
||||||
|
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
|
||||||
|
|
||||||
|
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||||
|
else evflag = 0;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
int **improperlist = neighbor->improperlist;
|
||||||
|
int nimproperlist = neighbor->nimproperlist;
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
// 1st bond
|
||||||
|
|
||||||
|
vb1x = x[i2][0] - x[i1][0];
|
||||||
|
vb1y = x[i2][1] - x[i1][1];
|
||||||
|
vb1z = x[i2][2] - x[i1][2];
|
||||||
|
domain->minimum_image(vb1x,vb1y,vb1z);
|
||||||
|
|
||||||
|
// 2nd bond
|
||||||
|
|
||||||
|
vb2x = x[i3][0] - x[i1][0];
|
||||||
|
vb2y = x[i3][1] - x[i1][1];
|
||||||
|
vb2z = x[i3][2] - x[i1][2];
|
||||||
|
domain->minimum_image(vb2x,vb2y,vb2z);
|
||||||
|
|
||||||
|
// 3rd bond
|
||||||
|
|
||||||
|
vb3x = x[i4][0] - x[i1][0];
|
||||||
|
vb3y = x[i4][1] - x[i1][1];
|
||||||
|
vb3z = x[i4][2] - x[i1][2];
|
||||||
|
domain->minimum_image(vb3x,vb3y,vb3z);
|
||||||
|
|
||||||
|
addone(i1,i2,i3,i4, type,evflag,eflag,
|
||||||
|
vb1x, vb1y, vb1z,
|
||||||
|
vb2x, vb2y, vb2z,
|
||||||
|
vb3x, vb3y, vb3z);
|
||||||
|
if ( all[type] ) {
|
||||||
|
addone(i1,i4,i2,i3, type,evflag,eflag,
|
||||||
|
vb3x, vb3y, vb3z,
|
||||||
|
vb1x, vb1y, vb1z,
|
||||||
|
vb2x, vb2y, vb2z);
|
||||||
|
addone(i1,i3,i4,i2, type,evflag,eflag,
|
||||||
|
vb2x, vb2y, vb2z,
|
||||||
|
vb3x, vb3y, vb3z,
|
||||||
|
vb1x, vb1y, vb1z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImproperFourier::addone(const int &i1,const int &i2,const int &i3,const int &i4,
|
||||||
|
const int &type,const int &evflag,const int &eflag,
|
||||||
|
const double &vb1x, const double &vb1y, const double &vb1z,
|
||||||
|
const double &vb2x, const double &vb2y, const double &vb2z,
|
||||||
|
const double &vb3x, const double &vb3y, const double &vb3z)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
double eimproper,f1[3],f2[3],f3[3],f4[3];
|
||||||
|
double domega,c,c2,a,s,projhfg,dhax,dhay,dhaz,dahx,dahy,dahz,cotphi;
|
||||||
|
double ax,ay,az,ra2,rh2,ra,rh,rar,rhr,arx,ary,arz,hrx,hry,hrz;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
double **f = atom->f;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int newton_bond = force->newton_bond;
|
||||||
|
|
||||||
|
eimproper = 0.0;
|
||||||
|
|
||||||
|
// c0 calculation
|
||||||
|
// A = vb1 X vb2 is perpendicular to IJK plane
|
||||||
|
|
||||||
|
ax = vb1y*vb2z-vb1z*vb2y;
|
||||||
|
ay = vb1z*vb2x-vb1x*vb2z;
|
||||||
|
az = vb1x*vb2y-vb1y*vb2x;
|
||||||
|
ra2 = ax*ax+ay*ay+az*az;
|
||||||
|
rh2 = vb3x*vb3x+vb3y*vb3y+vb3z*vb3z;
|
||||||
|
ra = sqrt(ra2);
|
||||||
|
rh = sqrt(rh2);
|
||||||
|
if (ra < SMALL) ra = SMALL;
|
||||||
|
if (rh < SMALL) rh = SMALL;
|
||||||
|
|
||||||
|
rar = 1/ra;
|
||||||
|
rhr = 1/rh;
|
||||||
|
arx = ax*rar;
|
||||||
|
ary = ay*rar;
|
||||||
|
arz = az*rar;
|
||||||
|
hrx = vb3x*rhr;
|
||||||
|
hry = vb3y*rhr;
|
||||||
|
hrz = vb3z*rhr;
|
||||||
|
|
||||||
|
c = arx*hrx+ary*hry+arz*hrz;
|
||||||
|
|
||||||
|
// error check
|
||||||
|
|
||||||
|
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||||
|
int me;
|
||||||
|
MPI_Comm_rank(world,&me);
|
||||||
|
if (screen) {
|
||||||
|
char str[128];
|
||||||
|
sprintf(str,
|
||||||
|
"Improper problem: %d " BIGINT_FORMAT " %d %d %d %d",
|
||||||
|
me,update->ntimestep,
|
||||||
|
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||||
|
error->warning(FLERR,str,0);
|
||||||
|
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) s = 1.0;
|
||||||
|
if (c < -1.0) s = -1.0;
|
||||||
|
|
||||||
|
s = sqrt(1.0 - c*c);
|
||||||
|
if (s < SMALL) s = SMALL;
|
||||||
|
cotphi = c/s;
|
||||||
|
|
||||||
|
projhfg = (vb3x*vb1x+vb3y*vb1y+vb3z*vb1z) /
|
||||||
|
sqrt(vb1x*vb1x+vb1y*vb1y+vb1z*vb1z);
|
||||||
|
projhfg += (vb3x*vb2x+vb3y*vb2y+vb3z*vb2z) /
|
||||||
|
sqrt(vb2x*vb2x+vb2y*vb2y+vb2z*vb2z);
|
||||||
|
if (projhfg > 0.0) {
|
||||||
|
s *= -1.0;
|
||||||
|
cotphi *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// force and energy
|
||||||
|
// E = k ( C0 + C1 cos(w) + C2 cos(w)
|
||||||
|
|
||||||
|
c2 = 2.0*s*s-1.0;
|
||||||
|
if (eflag) eimproper = k[type]*(C0[type]+C1[type]*s+C2[type]*c2);
|
||||||
|
|
||||||
|
// dhax = diffrence between H and A in X direction, etc
|
||||||
|
|
||||||
|
a = k[type]*(C1[type]+4.0*C2[type]*s)*cotphi;
|
||||||
|
dhax = hrx-c*arx;
|
||||||
|
dhay = hry-c*ary;
|
||||||
|
dhaz = hrz-c*arz;
|
||||||
|
|
||||||
|
dahx = arx-c*hrx;
|
||||||
|
dahy = ary-c*hry;
|
||||||
|
dahz = arz-c*hrz;
|
||||||
|
|
||||||
|
f2[0] = (dhay*vb1z - dhaz*vb1y)*rar;
|
||||||
|
f2[1] = (dhaz*vb1x - dhax*vb1z)*rar;
|
||||||
|
f2[2] = (dhax*vb1y - dhay*vb1x)*rar;
|
||||||
|
|
||||||
|
f3[0] = (-dhay*vb2z + dhaz*vb2y)*rar;
|
||||||
|
f3[1] = (-dhaz*vb2x + dhax*vb2z)*rar;
|
||||||
|
f3[2] = (-dhax*vb2y + dhay*vb2x)*rar;
|
||||||
|
|
||||||
|
f4[0] = dahx*rhr;
|
||||||
|
f4[1] = dahy*rhr;
|
||||||
|
f4[2] = dahz*rhr;
|
||||||
|
|
||||||
|
f1[0] = -(f2[0] + f3[0] + f4[0]);
|
||||||
|
f1[1] = -(f2[1] + f3[1] + f4[1]);
|
||||||
|
f1[2] = -(f2[2] + f3[2] + f4[2]);
|
||||||
|
|
||||||
|
// apply force to each of 4 atoms
|
||||||
|
|
||||||
|
if (newton_bond || i1 < nlocal) {
|
||||||
|
f[i1][0] += f1[0]*a;
|
||||||
|
f[i1][1] += f1[1]*a;
|
||||||
|
f[i1][2] += f1[2]*a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i2 < nlocal) {
|
||||||
|
f[i2][0] += f3[0]*a;
|
||||||
|
f[i2][1] += f3[1]*a;
|
||||||
|
f[i2][2] += f3[2]*a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i3 < nlocal) {
|
||||||
|
f[i3][0] += f2[0]*a;
|
||||||
|
f[i3][1] += f2[1]*a;
|
||||||
|
f[i3][2] += f2[2]*a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newton_bond || i4 < nlocal) {
|
||||||
|
f[i4][0] += f4[0]*a;
|
||||||
|
f[i4][1] += f4[1]*a;
|
||||||
|
f[i4][2] += f4[2]*a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evflag)
|
||||||
|
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,f1,f3,f4,
|
||||||
|
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ImproperFourier::allocate()
|
||||||
|
{
|
||||||
|
allocated = 1;
|
||||||
|
int n = atom->nimpropertypes;
|
||||||
|
|
||||||
|
memory->create(k,n+1,"improper:k");
|
||||||
|
memory->create(C0,n+1,"improper:C0");
|
||||||
|
memory->create(C1,n+1,"improper:C1");
|
||||||
|
memory->create(C2,n+1,"improper:C2");
|
||||||
|
memory->create(all,n+1,"improper:C2");
|
||||||
|
|
||||||
|
memory->create(setflag,n+1,"improper:setflag");
|
||||||
|
for (int i = 1; i <= n; i++) setflag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set coeffs for one type
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ImproperFourier::coeff(int narg, char **arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( narg != 5 && narg != 6 ) error->all(FLERR,"Incorrect args for improper coefficients");
|
||||||
|
|
||||||
|
if (!allocated) allocate();
|
||||||
|
|
||||||
|
int ilo,ihi;
|
||||||
|
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
|
||||||
|
|
||||||
|
double k_one = force->numeric(arg[1]);
|
||||||
|
double C0_one = force->numeric(arg[2]);
|
||||||
|
double C1_one = force->numeric(arg[3]);
|
||||||
|
double C2_one = force->numeric(arg[4]);
|
||||||
|
int all_one = 1;
|
||||||
|
if ( narg == 6 ) all_one = force->inumeric(arg[5]);
|
||||||
|
|
||||||
|
// convert w0 from degrees to radians
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = ilo; i <= ihi; i++) {
|
||||||
|
k[i] = k_one;
|
||||||
|
C0[i] = C0_one;
|
||||||
|
C1[i] = C1_one;
|
||||||
|
C2[i] = C2_one;
|
||||||
|
all[i] = all_one;
|
||||||
|
setflag[i] = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 writes out coeffs to restart file
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ImproperFourier::write_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
fwrite(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fwrite(&C0[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fwrite(&C1[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fwrite(&C2[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fwrite(&all[1],sizeof(int),atom->nimpropertypes,fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
proc 0 reads coeffs from restart file, bcasts them
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ImproperFourier::read_restart(FILE *fp)
|
||||||
|
{
|
||||||
|
allocate();
|
||||||
|
|
||||||
|
if (comm->me == 0) {
|
||||||
|
fread(&k[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fread(&C0[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fread(&C1[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fread(&C2[1],sizeof(double),atom->nimpropertypes,fp);
|
||||||
|
fread(&all[1],sizeof(int),atom->nimpropertypes,fp);
|
||||||
|
}
|
||||||
|
MPI_Bcast(&k[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C0[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C1[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&C2[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
|
||||||
|
MPI_Bcast(&all[1],atom->nimpropertypes,MPI_INT,0,world);
|
||||||
|
|
||||||
|
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
|
||||||
|
}
|
||||||
51
src/USER-MISC/improper_fourier.h
Normal file
51
src/USER-MISC/improper_fourier.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef IMPROPER_CLASS
|
||||||
|
|
||||||
|
ImproperStyle(fourier,ImproperFourier)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_IMPROPER_FOURIER_H
|
||||||
|
#define LMP_IMPROPER_FOURIER_H
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "improper.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class ImproperFourier : public Improper {
|
||||||
|
public:
|
||||||
|
ImproperFourier(class LAMMPS *);
|
||||||
|
~ImproperFourier();
|
||||||
|
void compute(int, int);
|
||||||
|
void coeff(int, char **);
|
||||||
|
void write_restart(FILE *);
|
||||||
|
void read_restart(FILE *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double *k, *C0, *C1, *C2;
|
||||||
|
int *all;
|
||||||
|
void addone(const int &i1,const int &i2,const int &i3,const int &i4,
|
||||||
|
const int &type,const int &evflag,const int &eflag,
|
||||||
|
const double &vb1x, const double &vb1y, const double &vb1z,
|
||||||
|
const double &vb2x, const double &vb2y, const double &vb2z,
|
||||||
|
const double &vb3x, const double &vb3y, const double &vb3z);
|
||||||
|
void allocate();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user