478 lines
14 KiB
C++
478 lines
14 KiB
C++
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
http://lammps.sandia.gov, Sandia National Laboratories
|
|
Steve Plimpton, sjplimp@sandia.gov
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
|
certain rights in this software. This software is distributed under
|
|
the GNU General Public License.
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
------------------------------------------------------------------------- */
|
|
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
#include "force.h"
|
|
#include "atom.h"
|
|
#include "comm.h"
|
|
#include "pair.h"
|
|
#include "pair_hybrid.h"
|
|
#include "bond.h"
|
|
#include "bond_hybrid.h"
|
|
#include "angle.h"
|
|
#include "dihedral.h"
|
|
#include "improper.h"
|
|
#include "kspace.h"
|
|
#include "group.h"
|
|
#include "memory.h"
|
|
#include "error.h"
|
|
|
|
#define BondInclude
|
|
#define AngleInclude
|
|
#define DihedralInclude
|
|
#define ImproperInclude
|
|
#define PairInclude
|
|
#define KSpaceInclude
|
|
#include "style.h"
|
|
#undef BondInclude
|
|
#undef AngleInclude
|
|
#undef DihedralInclude
|
|
#undef ImproperInclude
|
|
#undef PairInclude
|
|
#undef KSpaceInclude
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
Force::Force(LAMMPS *lmp) : Pointers(lmp)
|
|
{
|
|
newton = newton_pair = newton_bond = 1;
|
|
|
|
special_lj[1] = special_lj[2] = special_lj[3] = 0.0;
|
|
special_coul[1] = special_coul[2] = special_coul[3] = 0.0;
|
|
special_dihedral = 0;
|
|
special_extra = 0;
|
|
|
|
dielectric = 1.0;
|
|
|
|
pair = NULL;
|
|
bond = NULL;
|
|
angle = NULL;
|
|
dihedral = NULL;
|
|
improper = NULL;
|
|
kspace = NULL;
|
|
|
|
char *str = (char *) "none";
|
|
int n = strlen(str) + 1;
|
|
pair_style = new char[n];
|
|
strcpy(pair_style,str);
|
|
bond_style = new char[n];
|
|
strcpy(bond_style,str);
|
|
angle_style = new char[n];
|
|
strcpy(angle_style,str);
|
|
dihedral_style = new char[n];
|
|
strcpy(dihedral_style,str);
|
|
improper_style = new char[n];
|
|
strcpy(improper_style,str);
|
|
kspace_style = new char[n];
|
|
strcpy(kspace_style,str);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
Force::~Force()
|
|
{
|
|
delete [] pair_style;
|
|
delete [] bond_style;
|
|
delete [] angle_style;
|
|
delete [] dihedral_style;
|
|
delete [] improper_style;
|
|
delete [] kspace_style;
|
|
|
|
if (pair) delete pair;
|
|
if (bond) delete bond;
|
|
if (angle) delete angle;
|
|
if (dihedral) delete dihedral;
|
|
if (improper) delete improper;
|
|
if (kspace) delete kspace;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void Force::init()
|
|
{
|
|
qqrd2e = qqr2e/dielectric;
|
|
|
|
comm->maxforward_pair = comm->maxreverse_pair = 0;
|
|
|
|
if (kspace) kspace->init(); // kspace must come before pair
|
|
if (pair) pair->init(); // so g_ewald is defined
|
|
if (bond) bond->init();
|
|
if (angle) angle->init();
|
|
if (dihedral) dihedral->init();
|
|
if (improper) improper->init();
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a pair style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_pair(const char *style)
|
|
{
|
|
delete [] pair_style;
|
|
if (pair) delete pair;
|
|
|
|
pair = new_pair(style);
|
|
int n = strlen(style) + 1;
|
|
pair_style = new char[n];
|
|
strcpy(pair_style,style);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a pair class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Pair *Force::new_pair(const char *style)
|
|
{
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
|
|
#define PairClass
|
|
#define PairStyle(key,Class) \
|
|
else if (strcmp(style,#key) == 0) return new Class(lmp);
|
|
#include "style.h"
|
|
#undef PairClass
|
|
|
|
else error->all("Invalid pair style");
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to current pair class or hybrid sub-class
|
|
if exact, then style name must be exact match to word
|
|
if not exact, style name must contain word
|
|
else return NULL
|
|
------------------------------------------------------------------------- */
|
|
|
|
Pair *Force::pair_match(const char *word, int exact)
|
|
{
|
|
if (exact && strcmp(pair_style,word) == 0) return pair;
|
|
else if (!exact && strstr(pair_style,word)) return pair;
|
|
else if (strcmp(pair_style,"hybrid") == 0) {
|
|
PairHybrid *hybrid = (PairHybrid *) pair;
|
|
for (int i = 0; i < hybrid->nstyles; i++) {
|
|
if (exact && strcmp(hybrid->keywords[i],word) == 0)
|
|
return hybrid->styles[i];
|
|
else if (!exact && strstr(hybrid->keywords[i],word))
|
|
return hybrid->styles[i];
|
|
}
|
|
} else if (strcmp(pair_style,"hybrid/overlay") == 0) {
|
|
PairHybridOverlay *hybrid = (PairHybridOverlay *) pair;
|
|
for (int i = 0; i < hybrid->nstyles; i++) {
|
|
if (exact && strcmp(hybrid->keywords[i],word) == 0)
|
|
return hybrid->styles[i];
|
|
else if (!exact && strstr(hybrid->keywords[i],word))
|
|
return hybrid->styles[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a bond style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_bond(const char *style)
|
|
{
|
|
delete [] bond_style;
|
|
if (bond) delete bond;
|
|
|
|
bond = new_bond(style);
|
|
int n = strlen(style) + 1;
|
|
bond_style = new char[n];
|
|
strcpy(bond_style,style);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a bond class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Bond *Force::new_bond(const char *style)
|
|
{
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
|
|
#define BondClass
|
|
#define BondStyle(key,Class) \
|
|
else if (strcmp(style,#key) == 0) return new Class(lmp);
|
|
#include "style.h"
|
|
#undef BondClass
|
|
|
|
else error->all("Invalid bond style");
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to current bond class or hybrid sub-class if matches style
|
|
------------------------------------------------------------------------- */
|
|
|
|
Bond *Force::bond_match(const char *style)
|
|
{
|
|
if (strcmp(bond_style,style) == 0) return bond;
|
|
else if (strcmp(bond_style,"hybrid") == 0) {
|
|
BondHybrid *hybrid = (BondHybrid *) bond;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create an angle style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_angle(const char *style)
|
|
{
|
|
delete [] angle_style;
|
|
if (angle) delete angle;
|
|
|
|
angle = new_angle(style);
|
|
int n = strlen(style) + 1;
|
|
angle_style = new char[n];
|
|
strcpy(angle_style,style);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate an angle class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Angle *Force::new_angle(const char *style)
|
|
{
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
|
|
#define AngleClass
|
|
#define AngleStyle(key,Class) \
|
|
else if (strcmp(style,#key) == 0) return new Class(lmp);
|
|
#include "style.h"
|
|
#undef AngleClass
|
|
|
|
else error->all("Invalid angle style");
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a dihedral style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_dihedral(const char *style)
|
|
{
|
|
delete [] dihedral_style;
|
|
if (dihedral) delete dihedral;
|
|
|
|
dihedral = new_dihedral(style);
|
|
int n = strlen(style) + 1;
|
|
dihedral_style = new char[n];
|
|
strcpy(dihedral_style,style);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a dihedral class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Dihedral *Force::new_dihedral(const char *style)
|
|
{
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
|
|
#define DihedralClass
|
|
#define DihedralStyle(key,Class) \
|
|
else if (strcmp(style,#key) == 0) return new Class(lmp);
|
|
#include "style.h"
|
|
#undef DihedralClass
|
|
|
|
else error->all("Invalid dihedral style");
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create an improper style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_improper(const char *style)
|
|
{
|
|
delete [] improper_style;
|
|
if (improper) delete improper;
|
|
|
|
improper = new_improper(style);
|
|
int n = strlen(style) + 1;
|
|
improper_style = new char[n];
|
|
strcpy(improper_style,style);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a improper class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Improper *Force::new_improper(const char *style)
|
|
{
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
|
|
#define ImproperClass
|
|
#define ImproperStyle(key,Class) \
|
|
else if (strcmp(style,#key) == 0) return new Class(lmp);
|
|
#include "style.h"
|
|
#undef ImproperClass
|
|
|
|
else error->all("Invalid improper style");
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
new kspace style
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_kspace(int narg, char **arg)
|
|
{
|
|
delete [] kspace_style;
|
|
if (kspace) delete kspace;
|
|
|
|
if (strcmp(arg[0],"none") == 0) kspace = NULL;
|
|
|
|
#define KSpaceClass
|
|
#define KSpaceStyle(key,Class) \
|
|
else if (strcmp(arg[0],#key) == 0) kspace = new Class(lmp,narg-1,&arg[1]);
|
|
#include "style.h"
|
|
#undef KSpaceClass
|
|
|
|
else error->all("Invalid kspace style");
|
|
|
|
int n = strlen(arg[0]) + 1;
|
|
kspace_style = new char[n];
|
|
strcpy(kspace_style,arg[0]);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
set special bond values
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::set_special(int narg, char **arg)
|
|
{
|
|
if (narg == 0) error->all("Illegal special_bonds command");
|
|
|
|
int iarg = 0;
|
|
while (iarg < narg) {
|
|
if (strcmp(arg[iarg],"amber") == 0) {
|
|
if (iarg+1 > narg) error->all("Illegal special_bonds command");
|
|
special_lj[1] = 0.0;
|
|
special_lj[2] = 0.0;
|
|
special_lj[3] = 0.5;
|
|
special_coul[1] = 0.0;
|
|
special_coul[2] = 0.0;
|
|
special_coul[3] = 5.0/6.0;
|
|
iarg += 1;
|
|
} else if (strcmp(arg[iarg],"charmm") == 0) {
|
|
if (iarg+1 > narg) error->all("Illegal special_bonds command");
|
|
special_lj[1] = 0.0;
|
|
special_lj[2] = 0.0;
|
|
special_lj[3] = 0.0;
|
|
special_coul[1] = 0.0;
|
|
special_coul[2] = 0.0;
|
|
special_coul[3] = 0.0;
|
|
iarg += 1;
|
|
} else if (strcmp(arg[iarg],"fene") == 0) {
|
|
if (iarg+1 > narg) error->all("Illegal special_bonds command");
|
|
special_lj[1] = 0.0;
|
|
special_lj[2] = 1.0;
|
|
special_lj[3] = 1.0;
|
|
special_coul[1] = 0.0;
|
|
special_coul[2] = 1.0;
|
|
special_coul[3] = 1.0;
|
|
iarg += 1;
|
|
} else if (strcmp(arg[iarg],"lj/coul") == 0) {
|
|
if (iarg+4 > narg) error->all("Illegal special_bonds command");
|
|
special_lj[1] = special_coul[1] = atof(arg[iarg+1]);
|
|
special_lj[2] = special_coul[2] = atof(arg[iarg+2]);
|
|
special_lj[3] = special_coul[3] = atof(arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"lj") == 0) {
|
|
if (iarg+4 > narg) error->all("Illegal special_bonds command");
|
|
special_lj[1] = atof(arg[iarg+1]);
|
|
special_lj[2] = atof(arg[iarg+2]);
|
|
special_lj[3] = atof(arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"coul") == 0) {
|
|
if (iarg+4 > narg) error->all("Illegal special_bonds command");
|
|
special_coul[1] = atof(arg[iarg+1]);
|
|
special_coul[2] = atof(arg[iarg+2]);
|
|
special_coul[3] = atof(arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"dihedral") == 0) {
|
|
if (iarg+2 > narg) error->all("Illegal special_bonds command");
|
|
if (strcmp(arg[iarg+1],"no") == 0) special_dihedral = 0;
|
|
else if (strcmp(arg[iarg+1],"yes") == 0) special_dihedral = 1;
|
|
else error->all("Illegal special_bonds command");
|
|
iarg += 2;
|
|
} else if (strcmp(arg[iarg],"extra") == 0) {
|
|
if (iarg+2 > narg) error->all("Illegal special_bonds command");
|
|
special_extra = atoi(arg[iarg+1]);
|
|
iarg += 2;
|
|
} else error->all("Illegal special_bonds command");
|
|
}
|
|
|
|
for (int i = 1; i <= 3; i++)
|
|
if (special_lj[i] < 0.0 || special_lj[i] > 1.0 ||
|
|
special_coul[i] < 0.0 || special_coul[i] > 1.0)
|
|
error->all("Illegal special_bonds command");
|
|
|
|
if (special_extra < 0) error->all("Illegal special_bonds command");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
compute bounds implied by numeric str with a possible wildcard asterik
|
|
nmax = upper bound
|
|
5 possibilities:
|
|
(1) i = i to i, (2) * = 1 to nmax,
|
|
(3) i* = i to nmax, (4) *j = 1 to j, (5) i*j = i to j
|
|
return nlo,nhi
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::bounds(char *str, int nmax, int &nlo, int &nhi)
|
|
{
|
|
char *ptr = strchr(str,'*');
|
|
|
|
if (ptr == NULL) {
|
|
nlo = MAX(atoi(str),1);
|
|
nhi = MIN(atoi(str),nmax);
|
|
} else if (strlen(str) == 1) {
|
|
nlo = 1;
|
|
nhi = nmax;
|
|
} else if (ptr == str) {
|
|
nlo = 1;
|
|
nhi = MIN(atoi(ptr+1),nmax);
|
|
} else if (strlen(ptr+1) == 0) {
|
|
nlo = MAX(atoi(str),1);
|
|
nhi = nmax;
|
|
} else {
|
|
nlo = MAX(atoi(str),1);
|
|
nhi = MIN(atoi(ptr+1),nmax);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
memory usage of force classes
|
|
------------------------------------------------------------------------- */
|
|
|
|
double Force::memory_usage()
|
|
{
|
|
double bytes = 0.0;
|
|
if (pair) bytes += pair->memory_usage();
|
|
if (bond) bytes += bond->memory_usage();
|
|
if (angle) bytes += angle->memory_usage();
|
|
if (dihedral) bytes += dihedral->memory_usage();
|
|
if (improper) bytes += improper->memory_usage();
|
|
if (kspace) bytes += kspace->memory_usage();
|
|
return bytes;
|
|
}
|