forked from lijiext/lammps
1141 lines
34 KiB
C++
1141 lines
34 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 <ctype.h>
|
|
#include "force.h"
|
|
#include "style_bond.h"
|
|
#include "style_angle.h"
|
|
#include "style_dihedral.h"
|
|
#include "style_improper.h"
|
|
#include "style_pair.h"
|
|
#include "style_kspace.h"
|
|
#include "atom.h"
|
|
#include "comm.h"
|
|
#include "pair.h"
|
|
#include "pair_hybrid.h"
|
|
#include "pair_hybrid_overlay.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"
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
#define MAXLINE 1024
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
Force::Force(LAMMPS *lmp) : Pointers(lmp)
|
|
{
|
|
newton = newton_pair = newton_bond = 1;
|
|
|
|
special_lj[0] = special_coul[0] = 1.0;
|
|
special_lj[1] = special_lj[2] = special_lj[3] = 0.0;
|
|
special_coul[1] = special_coul[2] = special_coul[3] = 0.0;
|
|
special_angle = 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);
|
|
|
|
// fill pair map with pair styles listed in style_pair.h
|
|
|
|
pair_map = new PairCreatorMap();
|
|
|
|
#define PAIR_CLASS
|
|
#define PairStyle(key,Class) \
|
|
(*pair_map)[#key] = &pair_creator<Class>;
|
|
#include "style_pair.h"
|
|
#undef PairStyle
|
|
#undef PAIR_CLASS
|
|
|
|
bond_map = new BondCreatorMap();
|
|
|
|
#define BOND_CLASS
|
|
#define BondStyle(key,Class) \
|
|
(*bond_map)[#key] = &bond_creator<Class>;
|
|
#include "style_bond.h"
|
|
#undef BondStyle
|
|
#undef BOND_CLASS
|
|
|
|
angle_map = new AngleCreatorMap();
|
|
|
|
#define ANGLE_CLASS
|
|
#define AngleStyle(key,Class) \
|
|
(*angle_map)[#key] = &angle_creator<Class>;
|
|
#include "style_angle.h"
|
|
#undef AngleStyle
|
|
#undef ANGLE_CLASS
|
|
|
|
dihedral_map = new DihedralCreatorMap();
|
|
|
|
#define DIHEDRAL_CLASS
|
|
#define DihedralStyle(key,Class) \
|
|
(*dihedral_map)[#key] = &dihedral_creator<Class>;
|
|
#include "style_dihedral.h"
|
|
#undef DihedralStyle
|
|
#undef DIHEDRAL_CLASS
|
|
|
|
improper_map = new ImproperCreatorMap();
|
|
|
|
#define IMPROPER_CLASS
|
|
#define ImproperStyle(key,Class) \
|
|
(*improper_map)[#key] = &improper_creator<Class>;
|
|
#include "style_improper.h"
|
|
#undef ImproperStyle
|
|
#undef IMPROPER_CLASS
|
|
|
|
kspace_map = new KSpaceCreatorMap();
|
|
|
|
#define KSPACE_CLASS
|
|
#define KSpaceStyle(key,Class) \
|
|
(*kspace_map)[#key] = &kspace_creator<Class>;
|
|
#include "style_kspace.h"
|
|
#undef KSpaceStyle
|
|
#undef KSPACE_CLASS
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
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;
|
|
|
|
pair = NULL;
|
|
bond = NULL;
|
|
angle = NULL;
|
|
dihedral = NULL;
|
|
improper = NULL;
|
|
kspace = NULL;
|
|
|
|
delete pair_map;
|
|
delete bond_map;
|
|
delete angle_map;
|
|
delete dihedral_map;
|
|
delete improper_map;
|
|
delete kspace_map;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void Force::init()
|
|
{
|
|
qqrd2e = qqr2e/dielectric;
|
|
|
|
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();
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void Force::setup()
|
|
{
|
|
if (pair) pair->setup();
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a pair style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_pair(const char *style, int trysuffix)
|
|
{
|
|
delete [] pair_style;
|
|
if (pair) delete pair;
|
|
pair_style = NULL;
|
|
pair = NULL;
|
|
|
|
int sflag;
|
|
pair = new_pair(style,trysuffix,sflag);
|
|
store_style(pair_style,style,sflag);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a pair class
|
|
if trysuffix = 1, try first with suffix1/2 appended
|
|
return sflag = 0 for no suffix added, 1 or 2 for suffix1/2 added
|
|
------------------------------------------------------------------------- */
|
|
|
|
Pair *Force::new_pair(const char *style, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (pair_map->find(estyle) != pair_map->end()) {
|
|
PairCreator pair_creator = (*pair_map)[estyle];
|
|
return pair_creator(lmp);
|
|
}
|
|
}
|
|
if (lmp->suffix2) {
|
|
sflag = 2;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix2);
|
|
if (pair_map->find(estyle) != pair_map->end()) {
|
|
PairCreator pair_creator = (*pair_map)[estyle];
|
|
return pair_creator(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
if (pair_map->find(style) != pair_map->end()) {
|
|
PairCreator pair_creator = (*pair_map)[style];
|
|
return pair_creator(lmp);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown pair style %s",style);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per pair style in style_pair.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
Pair *Force::pair_creator(LAMMPS *lmp)
|
|
{
|
|
return new T(lmp);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to Pair class if matches word or matches hybrid sub-style
|
|
if exact, then style name must be exact match to word
|
|
if not exact, style name must contain word
|
|
if nsub > 0, match Nth hybrid sub-style
|
|
return NULL if no match or if nsub=0 and multiple sub-styles match
|
|
------------------------------------------------------------------------- */
|
|
|
|
Pair *Force::pair_match(const char *word, int exact, int nsub)
|
|
{
|
|
int iwhich,count;
|
|
|
|
if (exact && strcmp(pair_style,word) == 0) return pair;
|
|
else if (!exact && strstr(pair_style,word)) return pair;
|
|
|
|
else if (strstr(pair_style,"hybrid/overlay")) {
|
|
PairHybridOverlay *hybrid = (PairHybridOverlay *) pair;
|
|
count = 0;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if ((exact && strcmp(hybrid->keywords[i],word) == 0) ||
|
|
(!exact && strstr(hybrid->keywords[i],word))) {
|
|
iwhich = i;
|
|
count++;
|
|
if (nsub == count) return hybrid->styles[iwhich];
|
|
}
|
|
if (count == 1) return hybrid->styles[iwhich];
|
|
|
|
} else if (strstr(pair_style,"hybrid")) {
|
|
PairHybrid *hybrid = (PairHybrid *) pair;
|
|
count = 0;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if ((exact && strcmp(hybrid->keywords[i],word) == 0) ||
|
|
(!exact && strstr(hybrid->keywords[i],word))) {
|
|
iwhich = i;
|
|
count++;
|
|
if (nsub == count) return hybrid->styles[iwhich];
|
|
}
|
|
if (count == 1) return hybrid->styles[iwhich];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return style name of Pair class that matches Pair ptr
|
|
called by Neighbor::print_neigh_info()
|
|
return NULL if no match
|
|
------------------------------------------------------------------------- */
|
|
|
|
char *Force::pair_match_ptr(Pair *ptr)
|
|
{
|
|
if (ptr == pair) return pair_style;
|
|
|
|
if (strstr(pair_style,"hybrid")) {
|
|
PairHybrid *hybrid = (PairHybrid *) pair;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if (ptr == hybrid->styles[i]) return hybrid->keywords[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a bond style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_bond(const char *style, int trysuffix)
|
|
{
|
|
delete [] bond_style;
|
|
if (bond) delete bond;
|
|
|
|
int sflag;
|
|
bond = new_bond(style,trysuffix,sflag);
|
|
store_style(bond_style,style,sflag);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a bond class, fist with suffix appended
|
|
------------------------------------------------------------------------- */
|
|
|
|
Bond *Force::new_bond(const char *style, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (bond_map->find(estyle) != bond_map->end()) {
|
|
BondCreator bond_creator = (*bond_map)[estyle];
|
|
return bond_creator(lmp);
|
|
}
|
|
}
|
|
|
|
if (lmp->suffix2) {
|
|
sflag = 2;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix2);
|
|
if (bond_map->find(estyle) != bond_map->end()) {
|
|
BondCreator bond_creator = (*bond_map)[estyle];
|
|
return bond_creator(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
if (bond_map->find(style) != bond_map->end()) {
|
|
BondCreator bond_creator = (*bond_map)[style];
|
|
return bond_creator(lmp);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown bond style %s",style);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per bond style in style_bond.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
Bond *Force::bond_creator(LAMMPS *lmp)
|
|
{
|
|
return new T(lmp);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
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, int trysuffix)
|
|
{
|
|
delete [] angle_style;
|
|
if (angle) delete angle;
|
|
|
|
int sflag;
|
|
angle = new_angle(style,trysuffix,sflag);
|
|
store_style(angle_style,style,sflag);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate an angle class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Angle *Force::new_angle(const char *style, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (angle_map->find(estyle) != angle_map->end()) {
|
|
AngleCreator angle_creator = (*angle_map)[estyle];
|
|
return angle_creator(lmp);
|
|
}
|
|
}
|
|
|
|
if (lmp->suffix2) {
|
|
sflag = 2;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (angle_map->find(estyle) != angle_map->end()) {
|
|
AngleCreator angle_creator = (*angle_map)[estyle];
|
|
return angle_creator(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
if (angle_map->find(style) != angle_map->end()) {
|
|
AngleCreator angle_creator = (*angle_map)[style];
|
|
return angle_creator(lmp);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown angle style %s",style);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per angle style in style_angle.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
Angle *Force::angle_creator(LAMMPS *lmp)
|
|
{
|
|
return new T(lmp);
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to current angle class or hybrid sub-class if matches style
|
|
------------------------------------------------------------------------- */
|
|
|
|
Angle *Force::angle_match(const char *style)
|
|
{
|
|
if (strcmp(angle_style,style) == 0) return angle;
|
|
else if (strcmp(angle_style,"hybrid") == 0) {
|
|
AngleHybrid *hybrid = (AngleHybrid *) angle;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create a dihedral style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_dihedral(const char *style, int trysuffix)
|
|
{
|
|
delete [] dihedral_style;
|
|
if (dihedral) delete dihedral;
|
|
|
|
int sflag;
|
|
dihedral = new_dihedral(style,trysuffix,sflag);
|
|
store_style(dihedral_style,style,sflag);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a dihedral class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Dihedral *Force::new_dihedral(const char *style, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (dihedral_map->find(estyle) != dihedral_map->end()) {
|
|
DihedralCreator dihedral_creator = (*dihedral_map)[estyle];
|
|
return dihedral_creator(lmp);
|
|
}
|
|
}
|
|
|
|
if (lmp->suffix2) {
|
|
sflag = 2;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix2);
|
|
if (dihedral_map->find(estyle) != dihedral_map->end()) {
|
|
DihedralCreator dihedral_creator = (*dihedral_map)[estyle];
|
|
return dihedral_creator(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
if (dihedral_map->find(style) != dihedral_map->end()) {
|
|
DihedralCreator dihedral_creator = (*dihedral_map)[style];
|
|
return dihedral_creator(lmp);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown dihedral style %s",style);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per dihedral style in style_dihedral.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
Dihedral *Force::dihedral_creator(LAMMPS *lmp)
|
|
{
|
|
return new T(lmp);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to current angle class or hybrid sub-class if matches style
|
|
------------------------------------------------------------------------- */
|
|
|
|
Dihedral *Force::dihedral_match(const char *style)
|
|
{
|
|
if (strcmp(dihedral_style,style) == 0) return dihedral;
|
|
else if (strcmp(dihedral_style,"hybrid") == 0) {
|
|
DihedralHybrid *hybrid = (DihedralHybrid *) dihedral;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create an improper style, called from input script or restart file
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_improper(const char *style, int trysuffix)
|
|
{
|
|
delete [] improper_style;
|
|
if (improper) delete improper;
|
|
|
|
int sflag;
|
|
improper = new_improper(style,trysuffix,sflag);
|
|
store_style(improper_style,style,sflag);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a improper class
|
|
------------------------------------------------------------------------- */
|
|
|
|
Improper *Force::new_improper(const char *style, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
if (improper_map->find(estyle) != improper_map->end()) {
|
|
ImproperCreator improper_creator = (*improper_map)[estyle];
|
|
return improper_creator(lmp);
|
|
}
|
|
}
|
|
|
|
if (lmp->suffix2) {
|
|
sflag = 2;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",style,lmp->suffix2);
|
|
if (improper_map->find(estyle) != improper_map->end()) {
|
|
ImproperCreator improper_creator = (*improper_map)[estyle];
|
|
return improper_creator(lmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(style,"none") == 0) return NULL;
|
|
if (improper_map->find(style) != improper_map->end()) {
|
|
ImproperCreator improper_creator = (*improper_map)[style];
|
|
return improper_creator(lmp);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown improper style %s",style);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per improper style in style_improper.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
Improper *Force::improper_creator(LAMMPS *lmp)
|
|
{
|
|
return new T(lmp);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to current improper class or hybrid sub-class if matches style
|
|
------------------------------------------------------------------------- */
|
|
|
|
Improper *Force::improper_match(const char *style)
|
|
{
|
|
if (strcmp(improper_style,style) == 0) return improper;
|
|
else if (strcmp(improper_style,"hybrid") == 0) {
|
|
ImproperHybrid *hybrid = (ImproperHybrid *) improper;
|
|
for (int i = 0; i < hybrid->nstyles; i++)
|
|
if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
new kspace style
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::create_kspace(int narg, char **arg, int trysuffix)
|
|
{
|
|
delete [] kspace_style;
|
|
if (kspace) delete kspace;
|
|
|
|
int sflag;
|
|
kspace = new_kspace(narg,arg,trysuffix,sflag);
|
|
store_style(kspace_style,arg[0],sflag);
|
|
|
|
if (comm->style == 1 && !kspace_match("ewald",0))
|
|
error->all(FLERR,
|
|
"Cannot yet use KSpace solver with grid with comm style tiled");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
generate a kspace class
|
|
------------------------------------------------------------------------- */
|
|
|
|
KSpace *Force::new_kspace(int narg, char **arg, int trysuffix, int &sflag)
|
|
{
|
|
if (trysuffix && lmp->suffix_enable) {
|
|
if (lmp->suffix) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",arg[0],lmp->suffix);
|
|
if (kspace_map->find(estyle) != kspace_map->end()) {
|
|
KSpaceCreator kspace_creator = (*kspace_map)[estyle];
|
|
return kspace_creator(lmp, narg-1, &arg[1]);
|
|
}
|
|
}
|
|
|
|
if (lmp->suffix2) {
|
|
sflag = 1;
|
|
char estyle[256];
|
|
sprintf(estyle,"%s/%s",arg[0],lmp->suffix2);
|
|
if (kspace_map->find(estyle) != kspace_map->end()) {
|
|
KSpaceCreator kspace_creator = (*kspace_map)[estyle];
|
|
return kspace_creator(lmp, narg-1, &arg[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
sflag = 0;
|
|
if (strcmp(arg[0],"none") == 0) return NULL;
|
|
if (kspace_map->find(arg[0]) != kspace_map->end()) {
|
|
KSpaceCreator kspace_creator = (*kspace_map)[arg[0]];
|
|
return kspace_creator(lmp, narg-1, &arg[1]);
|
|
}
|
|
|
|
char str[128];
|
|
sprintf(str,"Unknown kspace style %s",arg[0]);
|
|
error->all(FLERR,str);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
one instance per kspace style in style_kspace.h
|
|
------------------------------------------------------------------------- */
|
|
|
|
template <typename T>
|
|
KSpace *Force::kspace_creator(LAMMPS *lmp, int narg, char ** arg)
|
|
{
|
|
return new T(lmp, narg, arg);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to Kspace class if matches word
|
|
if exact, then style name must be exact match to word
|
|
if not exact, style name must contain word
|
|
return NULL if no match
|
|
------------------------------------------------------------------------- */
|
|
|
|
KSpace *Force::kspace_match(const char *word, int exact)
|
|
{
|
|
if (exact && strcmp(kspace_style,word) == 0) return kspace;
|
|
else if (!exact && strstr(kspace_style,word)) return kspace;
|
|
return NULL;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
store style name in str allocated here
|
|
if sflag = 0, no suffix
|
|
if sflag = 1/2, append suffix or suffix2 to style
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::store_style(char *&str, const char *style, int sflag)
|
|
{
|
|
if (sflag) {
|
|
char estyle[256];
|
|
if (sflag == 1) sprintf(estyle,"%s/%s",style,lmp->suffix);
|
|
else sprintf(estyle,"%s/%s",style,lmp->suffix2);
|
|
int n = strlen(estyle) + 1;
|
|
str = new char[n];
|
|
strcpy(str,estyle);
|
|
} else {
|
|
int n = strlen(style) + 1;
|
|
str = new char[n];
|
|
strcpy(str,style);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
set special bond values
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::set_special(int narg, char **arg)
|
|
{
|
|
if (narg == 0) error->all(FLERR,"Illegal special_bonds command");
|
|
|
|
// defaults, but do not reset special_extra
|
|
|
|
special_lj[1] = special_lj[2] = special_lj[3] = 0.0;
|
|
special_coul[1] = special_coul[2] = special_coul[3] = 0.0;
|
|
special_angle = special_dihedral = 0;
|
|
|
|
int iarg = 0;
|
|
while (iarg < narg) {
|
|
if (strcmp(arg[iarg],"amber") == 0) {
|
|
if (iarg+1 > narg) error->all(FLERR,"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(FLERR,"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],"dreiding") == 0) {
|
|
if (iarg+1 > narg) error->all(FLERR,"Illegal special_bonds command");
|
|
special_lj[1] = 0.0;
|
|
special_lj[2] = 0.0;
|
|
special_lj[3] = 1.0;
|
|
special_coul[1] = 0.0;
|
|
special_coul[2] = 0.0;
|
|
special_coul[3] = 1.0;
|
|
iarg += 1;
|
|
} else if (strcmp(arg[iarg],"fene") == 0) {
|
|
if (iarg+1 > narg) error->all(FLERR,"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(FLERR,"Illegal special_bonds command");
|
|
special_lj[1] = special_coul[1] = numeric(FLERR,arg[iarg+1]);
|
|
special_lj[2] = special_coul[2] = numeric(FLERR,arg[iarg+2]);
|
|
special_lj[3] = special_coul[3] = numeric(FLERR,arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"lj") == 0) {
|
|
if (iarg+4 > narg) error->all(FLERR,"Illegal special_bonds command");
|
|
special_lj[1] = numeric(FLERR,arg[iarg+1]);
|
|
special_lj[2] = numeric(FLERR,arg[iarg+2]);
|
|
special_lj[3] = numeric(FLERR,arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"coul") == 0) {
|
|
if (iarg+4 > narg) error->all(FLERR,"Illegal special_bonds command");
|
|
special_coul[1] = numeric(FLERR,arg[iarg+1]);
|
|
special_coul[2] = numeric(FLERR,arg[iarg+2]);
|
|
special_coul[3] = numeric(FLERR,arg[iarg+3]);
|
|
iarg += 4;
|
|
} else if (strcmp(arg[iarg],"angle") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command");
|
|
if (strcmp(arg[iarg+1],"no") == 0) special_angle = 0;
|
|
else if (strcmp(arg[iarg+1],"yes") == 0) special_angle = 1;
|
|
else error->all(FLERR,"Illegal special_bonds command");
|
|
iarg += 2;
|
|
} else if (strcmp(arg[iarg],"dihedral") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"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(FLERR,"Illegal special_bonds command");
|
|
iarg += 2;
|
|
} else if (strcmp(arg[iarg],"extra") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command");
|
|
special_extra = atoi(arg[iarg+1]);
|
|
iarg += 2;
|
|
} else error->all(FLERR,"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(FLERR,"Illegal special_bonds command");
|
|
|
|
if (special_extra < 0) error->all(FLERR,"Illegal special_bonds command");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
compute bounds implied by numeric str with a possible wildcard asterik
|
|
1 = lower bound, nmax = upper bound
|
|
5 possibilities:
|
|
(1) i = i to i, (2) * = nmin to nmax,
|
|
(3) i* = i to nmax, (4) *j = nmin to j, (5) i*j = i to j
|
|
return nlo,nhi
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::bounds(const char *file, int line, char *str,
|
|
int nmax, int &nlo, int &nhi, int nmin)
|
|
{
|
|
char *ptr = strchr(str,'*');
|
|
|
|
if (ptr == NULL) {
|
|
nlo = nhi = atoi(str);
|
|
} else if (strlen(str) == 1) {
|
|
nlo = nmin;
|
|
nhi = nmax;
|
|
} else if (ptr == str) {
|
|
nlo = nmin;
|
|
nhi = atoi(ptr+1);
|
|
} else if (strlen(ptr+1) == 0) {
|
|
nlo = atoi(str);
|
|
nhi = nmax;
|
|
} else {
|
|
nlo = atoi(str);
|
|
nhi = atoi(ptr+1);
|
|
}
|
|
|
|
if (nlo < nmin || nhi > nmax || nlo > nhi)
|
|
error->all(file,line,"Numeric index is out of bounds");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
compute bounds implied by numeric str with a possible wildcard asterik
|
|
1 = lower bound, nmax = upper bound
|
|
5 possibilities:
|
|
(1) i = i to i, (2) * = nmin to nmax,
|
|
(3) i* = i to nmax, (4) *j = nmin to j, (5) i*j = i to j
|
|
return nlo,nhi
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::boundsbig(const char *file, int line, char *str,
|
|
bigint nmax, bigint &nlo, bigint &nhi, bigint nmin)
|
|
{
|
|
char *ptr = strchr(str,'*');
|
|
|
|
if (ptr == NULL) {
|
|
nlo = nhi = ATOBIGINT(str);
|
|
} else if (strlen(str) == 1) {
|
|
nlo = nmin;
|
|
nhi = nmax;
|
|
} else if (ptr == str) {
|
|
nlo = nmin;
|
|
nhi = ATOBIGINT(ptr+1);
|
|
} else if (strlen(ptr+1) == 0) {
|
|
nlo = ATOBIGINT(str);
|
|
nhi = nmax;
|
|
} else {
|
|
nlo = ATOBIGINT(str);
|
|
nhi = ATOBIGINT(ptr+1);
|
|
}
|
|
|
|
if (nlo < nmin || nhi > nmax || nlo > nhi)
|
|
error->all(file,line,"Numeric index is out of bounds");
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read a floating point value from a string
|
|
generate an error if not a legitimate floating point value
|
|
called by various commands to check validity of their arguments
|
|
------------------------------------------------------------------------- */
|
|
|
|
double Force::numeric(const char *file, int line, char *str)
|
|
{
|
|
if (!str)
|
|
error->all(file,line,"Expected floating point parameter "
|
|
"in input script or data file");
|
|
int n = strlen(str);
|
|
if (n == 0)
|
|
error->all(file,line,"Expected floating point parameter "
|
|
"in input script or data file");
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (isdigit(str[i])) continue;
|
|
if (str[i] == '-' || str[i] == '+' || str[i] == '.') continue;
|
|
if (str[i] == 'e' || str[i] == 'E') continue;
|
|
error->all(file,line,"Expected floating point parameter "
|
|
"in input script or data file");
|
|
}
|
|
|
|
return atof(str);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read an integer value from a string
|
|
generate an error if not a legitimate integer value
|
|
called by various commands to check validity of their arguments
|
|
------------------------------------------------------------------------- */
|
|
|
|
int Force::inumeric(const char *file, int line, char *str)
|
|
{
|
|
if (!str)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
int n = strlen(str);
|
|
if (n == 0)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (isdigit(str[i]) || str[i] == '-' || str[i] == '+') continue;
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
}
|
|
|
|
return atoi(str);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read a big integer value from a string
|
|
generate an error if not a legitimate integer value
|
|
called by various commands to check validity of their arguments
|
|
------------------------------------------------------------------------- */
|
|
|
|
bigint Force::bnumeric(const char *file, int line, char *str)
|
|
{
|
|
if (!str)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
int n = strlen(str);
|
|
if (n == 0)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (isdigit(str[i]) || str[i] == '-' || str[i] == '+') continue;
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
}
|
|
|
|
return ATOBIGINT(str);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read a tag integer value from a string
|
|
generate an error if not a legitimate integer value
|
|
called by various commands to check validity of their arguments
|
|
------------------------------------------------------------------------- */
|
|
|
|
tagint Force::tnumeric(const char *file, int line, char *str)
|
|
{
|
|
if (!str)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
int n = strlen(str);
|
|
if (n == 0)
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (isdigit(str[i]) || str[i] == '-' || str[i] == '+') continue;
|
|
error->all(file,line,
|
|
"Expected integer parameter in input script or data file");
|
|
}
|
|
|
|
return ATOTAGINT(str);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
open a potential file as specified by name
|
|
if fails, search in dir specified by env variable LAMMPS_POTENTIALS
|
|
------------------------------------------------------------------------- */
|
|
|
|
FILE *Force::open_potential(const char *name)
|
|
{
|
|
FILE *fp;
|
|
|
|
if (name == NULL) return NULL;
|
|
|
|
// attempt to open file directly
|
|
// if successful, return ptr
|
|
|
|
fp = fopen(name,"r");
|
|
if (fp) {
|
|
if (comm->me == 0) potential_date(fp,name);
|
|
rewind(fp);
|
|
return fp;
|
|
}
|
|
|
|
// try the environment variable directory
|
|
|
|
const char *path = getenv("LAMMPS_POTENTIALS");
|
|
if (path == NULL) return NULL;
|
|
|
|
const char *pot = potential_name(name);
|
|
if (pot == NULL) return NULL;
|
|
|
|
size_t len1 = strlen(path);
|
|
size_t len2 = strlen(pot);
|
|
char *newpath = new char[len1+len2+2];
|
|
|
|
strcpy(newpath,path);
|
|
#if defined(_WIN32)
|
|
newpath[len1] = '\\';
|
|
newpath[len1+1] = 0;
|
|
#else
|
|
newpath[len1] = '/';
|
|
newpath[len1+1] = 0;
|
|
#endif
|
|
strcat(newpath,pot);
|
|
|
|
fp = fopen(newpath,"r");
|
|
if (fp) {
|
|
if (comm->me == 0) potential_date(fp,name);
|
|
rewind(fp);
|
|
}
|
|
|
|
delete [] newpath;
|
|
return fp;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
strip off leading part of path, return just the filename
|
|
------------------------------------------------------------------------- */
|
|
|
|
const char *Force::potential_name(const char *path)
|
|
{
|
|
const char *pot;
|
|
|
|
if (path == NULL) return NULL;
|
|
|
|
#if defined(_WIN32)
|
|
// skip over the disk drive part of windows pathnames
|
|
if (isalpha(path[0]) && path[1] == ':')
|
|
path += 2;
|
|
#endif
|
|
|
|
for (pot = path; *path != '\0'; ++path) {
|
|
#if defined(_WIN32)
|
|
if ((*path == '\\') || (*path == '/')) pot = path + 1;
|
|
#else
|
|
if (*path == '/') pot = path + 1;
|
|
#endif
|
|
}
|
|
|
|
return pot;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
read first line of potential file
|
|
if has DATE field, print following word
|
|
------------------------------------------------------------------------- */
|
|
|
|
void Force::potential_date(FILE *fp, const char *name)
|
|
{
|
|
char line[MAXLINE];
|
|
char *ptr = fgets(line,MAXLINE,fp);
|
|
if (ptr == NULL) return;
|
|
|
|
char *word;
|
|
word = strtok(line," \t\n\r\f");
|
|
while (word) {
|
|
if (strcmp(word,"DATE:") == 0) {
|
|
word = strtok(NULL," \t\n\r\f");
|
|
if (word == NULL) return;
|
|
if (screen)
|
|
fprintf(screen,"Reading potential file %s with DATE: %s\n",name,word);
|
|
if (logfile)
|
|
fprintf(logfile,"Reading potential file %s with DATE: %s\n",name,word);
|
|
return;
|
|
}
|
|
word = strtok(NULL," \t\n\r\f");
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
memory usage of force classes
|
|
------------------------------------------------------------------------- */
|
|
|
|
bigint Force::memory_usage()
|
|
{
|
|
bigint bytes = 0;
|
|
if (pair) bytes += static_cast<bigint> (pair->memory_usage());
|
|
if (bond) bytes += static_cast<bigint> (bond->memory_usage());
|
|
if (angle) bytes += static_cast<bigint> (angle->memory_usage());
|
|
if (dihedral) bytes += static_cast<bigint> (dihedral->memory_usage());
|
|
if (improper) bytes += static_cast<bigint> (improper->memory_usage());
|
|
if (kspace) bytes += static_cast<bigint> (kspace->memory_usage());
|
|
return bytes;
|
|
}
|