diff --git a/src/MOLECULE/Install.sh b/src/MOLECULE/Install.sh index 5a30b0e86..5d9f853cf 100644 --- a/src/MOLECULE/Install.sh +++ b/src/MOLECULE/Install.sh @@ -1,147 +1,135 @@ # Install/unInstall package files in LAMMPS if (test $1 = 1) then cp angle_charmm.cpp .. cp angle_cosine.cpp .. cp angle_cosine_delta.cpp .. cp angle_cosine_periodic.cpp .. cp angle_cosine_squared.cpp .. cp angle_harmonic.cpp .. - cp angle_hybrid.cpp .. cp angle_table.cpp .. cp atom_vec_angle.cpp .. cp atom_vec_bond.cpp .. cp atom_vec_full.cpp .. cp atom_vec_molecular.cpp .. cp bond_fene.cpp .. cp bond_fene_expand.cpp .. cp bond_harmonic.cpp .. cp bond_morse.cpp .. cp bond_nonlinear.cpp .. cp bond_quartic.cpp .. cp bond_table.cpp .. cp dihedral_charmm.cpp .. cp dihedral_harmonic.cpp .. cp dihedral_helix.cpp .. - cp dihedral_hybrid.cpp .. cp dihedral_multi_harmonic.cpp .. cp dihedral_opls.cpp .. cp improper_cvff.cpp .. cp improper_harmonic.cpp .. - cp improper_hybrid.cpp .. cp improper_umbrella.cpp .. cp pair_hbond_dreiding_lj.cpp .. cp pair_hbond_dreiding_morse.cpp .. cp pair_lj_charmm_coul_charmm.cpp .. cp pair_lj_charmm_coul_charmm_implicit.cpp .. cp pair_lj_cut_tip4p_cut.cpp .. cp angle_charmm.h .. cp angle_cosine.h .. cp angle_cosine_delta.h .. cp angle_cosine_periodic.h .. cp angle_cosine_squared.h .. cp angle_harmonic.h .. - cp angle_hybrid.h .. cp angle_table.h .. cp atom_vec_angle.h .. cp atom_vec_bond.h .. cp atom_vec_full.h .. cp atom_vec_molecular.h .. cp bond_fene.h .. cp bond_fene_expand.h .. cp bond_harmonic.h .. cp bond_morse.h .. cp bond_nonlinear.h .. cp bond_quartic.h .. cp bond_table.h .. cp dihedral_charmm.h .. cp dihedral_harmonic.h .. cp dihedral_helix.h .. - cp dihedral_hybrid.h .. cp dihedral_multi_harmonic.h .. cp dihedral_opls.h .. cp improper_cvff.h .. cp improper_harmonic.h .. - cp improper_hybrid.h .. cp improper_umbrella.h .. cp pair_hbond_dreiding_lj.h .. cp pair_hbond_dreiding_morse.h .. cp pair_lj_charmm_coul_charmm.h .. cp pair_lj_charmm_coul_charmm_implicit.h .. cp pair_lj_cut_tip4p_cut.h .. elif (test $1 = 0) then rm -f ../angle_charmm.cpp rm -f ../angle_cosine.cpp rm -f ../angle_cosine_delta.cpp rm -f ../angle_cosine_periodic.cpp rm -f ../angle_cosine_squared.cpp rm -f ../angle_harmonic.cpp - rm -f ../angle_hybrid.cpp rm -f ../angle_table.cpp rm -f ../atom_vec_angle.cpp rm -f ../atom_vec_bond.cpp rm -f ../atom_vec_full.cpp rm -f ../atom_vec_molecular.cpp rm -f ../bond_fene.cpp rm -f ../bond_fene_expand.cpp rm -f ../bond_harmonic.cpp rm -f ../bond_morse.cpp rm -f ../bond_nonlinear.cpp rm -f ../bond_quartic.cpp rm -f ../bond_table.cpp rm -f ../dihedral_charmm.cpp rm -f ../dihedral_harmonic.cpp rm -f ../dihedral_helix.cpp - rm -f ../dihedral_hybrid.cpp rm -f ../dihedral_multi_harmonic.cpp rm -f ../dihedral_opls.cpp rm -f ../improper_cvff.cpp rm -f ../improper_harmonic.cpp - rm -f ../improper_hybrid.cpp rm -f ../improper_umbrella.cpp rm -f ../pair_hbond_dreiding_lj.cpp rm -f ../pair_hbond_dreiding_morse.cpp rm -f ../pair_lj_charmm_coul_charmm.cpp rm -f ../pair_lj_charmm_coul_charmm_implicit.cpp rm -f ../pair_lj_cut_tip4p_cut.cpp rm -f ../angle_charmm.h rm -f ../angle_cosine.h rm -f ../angle_cosine_delta.h rm -f ../angle_cosine_periodic.h rm -f ../angle_cosine_squared.h rm -f ../angle_harmonic.h - rm -f ../angle_hybrid.h rm -f ../angle_table.h rm -f ../atom_vec_angle.h rm -f ../atom_vec_bond.h rm -f ../atom_vec_full.h rm -f ../atom_vec_molecular.h rm -f ../bond_fene.h rm -f ../bond_fene_expand.h rm -f ../bond_harmonic.h rm -f ../bond_morse.h rm -f ../bond_nonlinear.h rm -f ../bond_quartic.h rm -f ../bond_table.h rm -f ../dihedral_charmm.h rm -f ../dihedral_harmonic.h rm -f ../dihedral_helix.h - rm -f ../dihedral_hybrid.h rm -f ../dihedral_multi_harmonic.h rm -f ../dihedral_opls.h rm -f ../improper_cvff.h rm -f ../improper_harmonic.h - rm -f ../improper_hybrid.h rm -f ../improper_umbrella.h rm -f ../pair_hbond_dreiding_lj.h rm -f ../pair_hbond_dreiding_morse.h rm -f ../pair_lj_charmm_coul_charmm.h rm -f ../pair_lj_charmm_coul_charmm_implicit.h rm -f ../pair_lj_cut_tip4p_cut.h fi diff --git a/src/angle_hybrid.cpp b/src/angle_hybrid.cpp new file mode 100644 index 000000000..36e8e8888 --- /dev/null +++ b/src/angle_hybrid.cpp @@ -0,0 +1,368 @@ +/* ---------------------------------------------------------------------- + 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 "math.h" +#include "string.h" +#include "ctype.h" +#include "angle_hybrid.h" +#include "atom.h" +#include "neighbor.h" +#include "domain.h" +#include "comm.h" +#include "force.h" +#include "memory.h" +#include "error.h" + +using namespace LAMMPS_NS; + +#define EXTRA 1000 + +/* ---------------------------------------------------------------------- */ + +AngleHybrid::AngleHybrid(LAMMPS *lmp) : Angle(lmp) +{ + nstyles = 0; +} + +/* ---------------------------------------------------------------------- */ + +AngleHybrid::~AngleHybrid() +{ + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] nanglelist; + delete [] maxangle; + for (int i = 0; i < nstyles; i++) + memory->destroy(anglelist[i]); + delete [] anglelist; + } +} + +/* ---------------------------------------------------------------------- */ + +void AngleHybrid::compute(int eflag, int vflag) +{ + int i,j,m,n; + + // save ptrs to original anglelist + + int nanglelist_orig = neighbor->nanglelist; + int **anglelist_orig = neighbor->anglelist; + + // if this is re-neighbor step, create sub-style anglelists + // nanglelist[] = length of each sub-style list + // realloc sub-style anglelist if necessary + // load sub-style anglelist with 4 values from original anglelist + + if (neighbor->ago == 0) { + for (m = 0; m < nstyles; m++) nanglelist[m] = 0; + for (i = 0; i < nanglelist_orig; i++) { + m = map[anglelist_orig[i][3]]; + if (m >= 0) nanglelist[m]++; + } + for (m = 0; m < nstyles; m++) { + if (nanglelist[m] > maxangle[m]) { + memory->destroy(anglelist[m]); + maxangle[m] = nanglelist[m] + EXTRA; + memory->create(anglelist[m],maxangle[m],4,"angle_hybrid:anglelist"); + } + nanglelist[m] = 0; + } + for (i = 0; i < nanglelist_orig; i++) { + m = map[anglelist_orig[i][3]]; + if (m < 0) continue; + n = nanglelist[m]; + anglelist[m][n][0] = anglelist_orig[i][0]; + anglelist[m][n][1] = anglelist_orig[i][1]; + anglelist[m][n][2] = anglelist_orig[i][2]; + anglelist[m][n][3] = anglelist_orig[i][3]; + nanglelist[m]++; + } + } + + // call each sub-style's compute function + // set neighbor->anglelist to sub-style anglelist before call + // accumulate sub-style global/peratom energy/virial in hybrid + + if (eflag || vflag) ev_setup(eflag,vflag); + else evflag = 0; + + for (m = 0; m < nstyles; m++) { + neighbor->nanglelist = nanglelist[m]; + neighbor->anglelist = anglelist[m]; + + styles[m]->compute(eflag,vflag); + + if (eflag_global) energy += styles[m]->energy; + if (vflag_global) + for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n]; + if (eflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double *eatom_substyle = styles[m]->eatom; + for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i]; + } + if (vflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double **vatom_substyle = styles[m]->vatom; + for (i = 0; i < n; i++) + for (j = 0; j < 6; j++) + vatom[i][j] += vatom_substyle[i][j]; + } + } + + // restore ptrs to original anglelist + + neighbor->nanglelist = nanglelist_orig; + neighbor->anglelist = anglelist_orig; +} + +/* ---------------------------------------------------------------------- */ + +void AngleHybrid::allocate() +{ + allocated = 1; + int n = atom->nangletypes; + + memory->create(map,n+1,"angle:map"); + memory->create(setflag,n+1,"angle:setflag"); + for (int i = 1; i <= n; i++) setflag[i] = 0; + + nanglelist = new int[nstyles]; + maxangle = new int[nstyles]; + anglelist = new int**[nstyles]; + for (int m = 0; m < nstyles; m++) maxangle[m] = 0; + for (int m = 0; m < nstyles; m++) anglelist[m] = NULL; +} + +/* ---------------------------------------------------------------------- + create one angle style for each arg in list +------------------------------------------------------------------------- */ + +void AngleHybrid::settings(int narg, char **arg) +{ + int i,m,istyle; + + if (narg < 1) error->all(FLERR,"Illegal angle_style command"); + + // delete old lists, since cannot just change settings + + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] nanglelist; + delete [] maxangle; + for (int i = 0; i < nstyles; i++) + memory->destroy(anglelist[i]); + delete [] anglelist; + } + allocated = 0; + + // count sub-styles by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric word + // need a better way to skip these exceptions + + nstyles = 0; + i = 0; + while (i < narg) { + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + nstyles++; + } + + // allocate list of sub-styles + + styles = new Angle*[nstyles]; + keywords = new char*[nstyles]; + + // allocate each sub-style and call its settings() with subset of args + // define subset of args for a sub-style by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric + // need a better way to skip these exceptions + + int dummy; + nstyles = 0; + i = 0; + + while (i < narg) { + for (m = 0; m < nstyles; m++) + if (strcmp(arg[i],keywords[m]) == 0) + error->all(FLERR,"Angle style hybrid cannot use " + "same angle style twice"); + if (strcmp(arg[i],"hybrid") == 0) + error->all(FLERR,"Angle style hybrid cannot have hybrid as an argument"); + if (strcmp(arg[i],"none") == 0) + error->all(FLERR,"Angle style hybrid cannot have none as an argument"); + styles[nstyles] = force->new_angle(arg[i],lmp->suffix,dummy); + keywords[nstyles] = new char[strlen(arg[i])+1]; + strcpy(keywords[nstyles],arg[i]); + istyle = i; + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]); + nstyles++; + } +} + +/* ---------------------------------------------------------------------- + set coeffs for one type +---------------------------------------------------------------------- */ + +void AngleHybrid::coeff(int narg, char **arg) +{ + if (!allocated) allocate(); + + int ilo,ihi; + force->bounds(arg[0],atom->nangletypes,ilo,ihi); + + // 2nd arg = angle sub-style name + // allow for "none" or "skip" as valid sub-style name + + int m; + for (m = 0; m < nstyles; m++) + if (strcmp(arg[1],keywords[m]) == 0) break; + + int none = 0; + int skip = 0; + if (m == nstyles) { + if (strcmp(arg[1],"none") == 0) none = 1; + else if (strcmp(arg[1],"skip") == 0) none = skip = 1; + else error->all(FLERR,"Angle coeff for hybrid has invalid style"); + } + + // move 1st arg to 2nd arg + // just copy ptrs, since arg[] points into original input line + + arg[1] = arg[0]; + + // invoke sub-style coeff() starting with 1st arg + + if (!none) styles[m]->coeff(narg-1,&arg[1]); + + // set setflag and which type maps to which sub-style + // if sub-style is skip: auxiliary class2 setting in data file so ignore + // if sub-style is none: set hybrid setflag, wipe out map + + for (int i = ilo; i <= ihi; i++) { + if (skip) continue; + else if (none) { + setflag[i] = 1; + map[i] = -1; + } else { + setflag[i] = styles[m]->setflag[i]; + map[i] = m; + } + } +} + +/* ---------------------------------------------------------------------- + run angle style specific initialization +------------------------------------------------------------------------- */ + +void AngleHybrid::init_style() +{ + for (int m = 0; m < nstyles; m++) + if (styles[m]) styles[m]->init_style(); +} + +/* ---------------------------------------------------------------------- + return an equilbrium angle length +------------------------------------------------------------------------- */ + +double AngleHybrid::equilibrium_angle(int i) +{ + if (map[i] < 0) + error->one(FLERR,"Invoked angle equil angle on angle style none"); + return styles[map[i]]->equilibrium_angle(i); +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void AngleHybrid::write_restart(FILE *fp) +{ + fwrite(&nstyles,sizeof(int),1,fp); + + int n; + for (int m = 0; m < nstyles; m++) { + n = strlen(keywords[m]) + 1; + fwrite(&n,sizeof(int),1,fp); + fwrite(keywords[m],sizeof(char),n,fp); + } +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void AngleHybrid::read_restart(FILE *fp) +{ + int me = comm->me; + if (me == 0) fread(&nstyles,sizeof(int),1,fp); + MPI_Bcast(&nstyles,1,MPI_INT,0,world); + styles = new Angle*[nstyles]; + keywords = new char*[nstyles]; + + allocate(); + + int n,dummy; + for (int m = 0; m < nstyles; m++) { + if (me == 0) fread(&n,sizeof(int),1,fp); + MPI_Bcast(&n,1,MPI_INT,0,world); + keywords[m] = new char[n]; + if (me == 0) fread(keywords[m],sizeof(char),n,fp); + MPI_Bcast(keywords[m],n,MPI_CHAR,0,world); + styles[m] = force->new_angle(keywords[m],lmp->suffix,dummy); + } +} + +/* ---------------------------------------------------------------------- */ + +double AngleHybrid::single(int type, int i1, int i2, int i3) +{ + if (map[type] < 0) error->one(FLERR,"Invoked angle single on angle style none"); + return styles[map[type]]->single(type,i1,i2,i3); +} + +/* ---------------------------------------------------------------------- + memory usage +------------------------------------------------------------------------- */ + +double AngleHybrid::memory_usage() +{ + double bytes = maxeatom * sizeof(double); + bytes += maxvatom*6 * sizeof(double); + for (int m = 0; m < nstyles; m++) bytes += maxangle[m]*4 * sizeof(int); + for (int m = 0; m < nstyles; m++) + if (styles[m]) bytes += styles[m]->memory_usage(); + return bytes; +} diff --git a/src/angle_hybrid.h b/src/angle_hybrid.h new file mode 100644 index 000000000..cd14178d8 --- /dev/null +++ b/src/angle_hybrid.h @@ -0,0 +1,95 @@ +/* ---------------------------------------------------------------------- + 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(hybrid,AngleHybrid) + +#else + +#ifndef LMP_ANGLE_HYBRID_H +#define LMP_ANGLE_HYBRID_H + +#include "stdio.h" +#include "angle.h" + +namespace LAMMPS_NS { + +class AngleHybrid : public Angle { + public: + int nstyles; // # of different angle styles + Angle **styles; // class list for each Angle style + char **keywords; // keyword for each Angle style + + AngleHybrid(class LAMMPS *); + ~AngleHybrid(); + void compute(int, int); + void settings(int, char **); + void coeff(int, char **); + void init_style(); + double equilibrium_angle(int); + void write_restart(FILE *); + void read_restart(FILE *); + double single(int, int, int, int); + double memory_usage(); + + private: + int *map; // which style each angle type points to + + int *nanglelist; // # of angles in sub-style anglelists + int *maxangle; // max # of angles sub-style lists can store + int ***anglelist; // anglelist for each sub-style + + void allocate(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Angle style hybrid cannot use same angle style twice + +Self-explanatory. + +E: Angle style hybrid cannot have hybrid as an argument + +Self-explanatory. + +E: Angle style hybrid cannot have none as an argument + +Self-explanatory. + +E: Angle coeff for hybrid has invalid style + +Angle style hybrid uses another angle style as one of its +coefficients. The angle style used in the angle_coeff command or read +from a restart file is not recognized. + +E: Invoked angle equil angle on angle style none + +Self-explanatory. + +E: Invoked angle single on angle style none + +Self-explanatory. + +*/ diff --git a/src/dihedral_hybrid.cpp b/src/dihedral_hybrid.cpp new file mode 100644 index 000000000..7b0dea64d --- /dev/null +++ b/src/dihedral_hybrid.cpp @@ -0,0 +1,350 @@ +/* ---------------------------------------------------------------------- + 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 "math.h" +#include "string.h" +#include "ctype.h" +#include "dihedral_hybrid.h" +#include "atom.h" +#include "neighbor.h" +#include "domain.h" +#include "comm.h" +#include "force.h" +#include "memory.h" +#include "error.h" + +using namespace LAMMPS_NS; + +#define EXTRA 1000 + +/* ---------------------------------------------------------------------- */ + +DihedralHybrid::DihedralHybrid(LAMMPS *lmp) : Dihedral(lmp) +{ + nstyles = 0; +} + +/* ---------------------------------------------------------------------- */ + +DihedralHybrid::~DihedralHybrid() +{ + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] ndihedrallist; + delete [] maxdihedral; + for (int i = 0; i < nstyles; i++) + memory->destroy(dihedrallist[i]); + delete [] dihedrallist; + } +} + +/* ---------------------------------------------------------------------- */ + +void DihedralHybrid::compute(int eflag, int vflag) +{ + int i,j,m,n; + + // save ptrs to original dihedrallist + + int ndihedrallist_orig = neighbor->ndihedrallist; + int **dihedrallist_orig = neighbor->dihedrallist; + + // if this is re-neighbor step, create sub-style dihedrallists + // ndihedrallist[] = length of each sub-style list + // realloc sub-style dihedrallist if necessary + // load sub-style dihedrallist with 5 values from original dihedrallist + + if (neighbor->ago == 0) { + for (m = 0; m < nstyles; m++) ndihedrallist[m] = 0; + for (i = 0; i < ndihedrallist_orig; i++) { + m = map[dihedrallist_orig[i][4]]; + if (m >= 0) ndihedrallist[m]++; + } + for (m = 0; m < nstyles; m++) { + if (ndihedrallist[m] > maxdihedral[m]) { + memory->destroy(dihedrallist[m]); + maxdihedral[m] = ndihedrallist[m] + EXTRA; + memory->create(dihedrallist[m],maxdihedral[m],5, + "dihedral_hybrid:dihedrallist"); + } + ndihedrallist[m] = 0; + } + for (i = 0; i < ndihedrallist_orig; i++) { + m = map[dihedrallist_orig[i][4]]; + if (m < 0) continue; + n = ndihedrallist[m]; + dihedrallist[m][n][0] = dihedrallist_orig[i][0]; + dihedrallist[m][n][1] = dihedrallist_orig[i][1]; + dihedrallist[m][n][2] = dihedrallist_orig[i][2]; + dihedrallist[m][n][3] = dihedrallist_orig[i][3]; + dihedrallist[m][n][4] = dihedrallist_orig[i][4]; + ndihedrallist[m]++; + } + } + + // call each sub-style's compute function + // set neighbor->dihedrallist to sub-style dihedrallist before call + // accumulate sub-style global/peratom energy/virial in hybrid + + if (eflag || vflag) ev_setup(eflag,vflag); + else evflag = 0; + + for (m = 0; m < nstyles; m++) { + neighbor->ndihedrallist = ndihedrallist[m]; + neighbor->dihedrallist = dihedrallist[m]; + + styles[m]->compute(eflag,vflag); + + if (eflag_global) energy += styles[m]->energy; + if (vflag_global) + for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n]; + if (eflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double *eatom_substyle = styles[m]->eatom; + for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i]; + } + if (vflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double **vatom_substyle = styles[m]->vatom; + for (i = 0; i < n; i++) + for (j = 0; j < 6; j++) + vatom[i][j] += vatom_substyle[i][j]; + } + } + + // restore ptrs to original dihedrallist + + neighbor->ndihedrallist = ndihedrallist_orig; + neighbor->dihedrallist = dihedrallist_orig; +} + +/* ---------------------------------------------------------------------- */ + +void DihedralHybrid::allocate() +{ + allocated = 1; + int n = atom->ndihedraltypes; + + memory->create(map,n+1,"dihedral:map"); + memory->create(setflag,n+1,"dihedral:setflag"); + for (int i = 1; i <= n; i++) setflag[i] = 0; + + ndihedrallist = new int[nstyles]; + maxdihedral = new int[nstyles]; + dihedrallist = new int**[nstyles]; + for (int m = 0; m < nstyles; m++) maxdihedral[m] = 0; + for (int m = 0; m < nstyles; m++) dihedrallist[m] = NULL; +} + +/* ---------------------------------------------------------------------- + create one dihedral style for each arg in list +------------------------------------------------------------------------- */ + +void DihedralHybrid::settings(int narg, char **arg) +{ + int i,m,istyle; + + if (narg < 1) error->all(FLERR,"Illegal dihedral_style command"); + + // delete old lists, since cannot just change settings + + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] ndihedrallist; + delete [] maxdihedral; + for (int i = 0; i < nstyles; i++) + memory->destroy(dihedrallist[i]); + delete [] dihedrallist; + } + allocated = 0; + + // count sub-styles by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric word + // need a better way to skip these exceptions + + nstyles = 0; + i = 0; + while (i < narg) { + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + nstyles++; + } + + // allocate list of sub-styles + + styles = new Dihedral*[nstyles]; + keywords = new char*[nstyles]; + + // allocate each sub-style and call its settings() with subset of args + // define subset of args for a sub-style by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric + // need a better way to skip these exceptions + + int dummy; + nstyles = 0; + i = 0; + + while (i < narg) { + for (m = 0; m < nstyles; m++) + if (strcmp(arg[i],keywords[m]) == 0) + error->all(FLERR,"Dihedral style hybrid cannot use " + "same dihedral style twice"); + if (strcmp(arg[i],"hybrid") == 0) + error->all(FLERR, + "Dihedral style hybrid cannot have hybrid as an argument"); + if (strcmp(arg[i],"none") == 0) + error->all(FLERR,"Dihedral style hybrid cannot have none as an argument"); + styles[nstyles] = force->new_dihedral(arg[i],lmp->suffix,dummy); + keywords[nstyles] = new char[strlen(arg[i])+1]; + strcpy(keywords[nstyles],arg[i]); + istyle = i; + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]); + nstyles++; + } +} + +/* ---------------------------------------------------------------------- + set coeffs for one type +---------------------------------------------------------------------- */ + +void DihedralHybrid::coeff(int narg, char **arg) +{ + if (!allocated) allocate(); + + int ilo,ihi; + force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi); + + // 2nd arg = dihedral sub-style name + // allow for "none" or "skip" as valid sub-style name + + int m; + for (m = 0; m < nstyles; m++) + if (strcmp(arg[1],keywords[m]) == 0) break; + + int none = 0; + int skip = 0; + if (m == nstyles) { + if (strcmp(arg[1],"none") == 0) none = 1; + else if (strcmp(arg[1],"skip") == 0) none = skip = 1; + else error->all(FLERR,"Dihedral coeff for hybrid has invalid style"); + } + + // move 1st arg to 2nd arg + // just copy ptrs, since arg[] points into original input line + + arg[1] = arg[0]; + + // invoke sub-style coeff() starting with 1st arg + + if (!none) styles[m]->coeff(narg-1,&arg[1]); + + // set setflag and which type maps to which sub-style + // if sub-style is skip: auxiliary class2 setting in data file so ignore + // if sub-style is none and not skip: set hybrid setflag, wipe out map + + for (int i = ilo; i <= ihi; i++) { + if (skip) continue; + else if (none) { + setflag[i] = 1; + map[i] = -1; + } else { + setflag[i] = styles[m]->setflag[i]; + map[i] = m; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void DihedralHybrid::init_style() +{ + for (int m = 0; m < nstyles; m++) + if (styles[m]) styles[m]->init_style(); +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void DihedralHybrid::write_restart(FILE *fp) +{ + fwrite(&nstyles,sizeof(int),1,fp); + + int n; + for (int m = 0; m < nstyles; m++) { + n = strlen(keywords[m]) + 1; + fwrite(&n,sizeof(int),1,fp); + fwrite(keywords[m],sizeof(char),n,fp); + } +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void DihedralHybrid::read_restart(FILE *fp) +{ + int me = comm->me; + if (me == 0) fread(&nstyles,sizeof(int),1,fp); + MPI_Bcast(&nstyles,1,MPI_INT,0,world); + styles = new Dihedral*[nstyles]; + keywords = new char*[nstyles]; + + allocate(); + + int n,dummy; + for (int m = 0; m < nstyles; m++) { + if (me == 0) fread(&n,sizeof(int),1,fp); + MPI_Bcast(&n,1,MPI_INT,0,world); + keywords[m] = new char[n]; + if (me == 0) fread(keywords[m],sizeof(char),n,fp); + MPI_Bcast(keywords[m],n,MPI_CHAR,0,world); + styles[m] = force->new_dihedral(keywords[m],lmp->suffix,dummy); + } +} + +/* ---------------------------------------------------------------------- + memory usage +------------------------------------------------------------------------- */ + +double DihedralHybrid::memory_usage() +{ + double bytes = maxeatom * sizeof(double); + bytes += maxvatom*6 * sizeof(double); + for (int m = 0; m < nstyles; m++) bytes += maxdihedral[m]*5 * sizeof(int); + for (int m = 0; m < nstyles; m++) + if (styles[m]) bytes += styles[m]->memory_usage(); + return bytes; +} diff --git a/src/dihedral_hybrid.h b/src/dihedral_hybrid.h new file mode 100644 index 000000000..1526415c4 --- /dev/null +++ b/src/dihedral_hybrid.h @@ -0,0 +1,85 @@ +/* ---------------------------------------------------------------------- + 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(hybrid,DihedralHybrid) + +#else + +#ifndef LMP_DIHEDRAL_HYBRID_H +#define LMP_DIHEDRAL_HYBRID_H + +#include "stdio.h" +#include "dihedral.h" + +namespace LAMMPS_NS { + +class DihedralHybrid : public Dihedral { + public: + int nstyles; // # of different dihedral styles + Dihedral **styles; // class list for each Dihedral style + char **keywords; // keyword for each dihedral style + + DihedralHybrid(class LAMMPS *); + ~DihedralHybrid(); + void compute(int, int); + void settings(int, char **); + void coeff(int, char **); + void init_style(); + void write_restart(FILE *); + void read_restart(FILE *); + double memory_usage(); + + private: + int *map; // which style each dihedral type points to + + int *ndihedrallist; // # of dihedrals in sub-style dihedrallists + int *maxdihedral; // max # of dihedrals sub-style lists can store + int ***dihedrallist; // dihedrallist for each sub-style + + void allocate(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Dihedral style hybrid cannot use same dihedral style twice + +Self-explanatory. + +E: Dihedral style hybrid cannot have hybrid as an argument + +Self-explanatory. + +E: Dihedral style hybrid cannot have none as an argument + +Self-explanatory. + +E: Dihedral coeff for hybrid has invalid style + +Dihedral style hybrid uses another dihedral style as one of its +coefficients. The dihedral style used in the dihedral_coeff command +or read from a restart file is not recognized. + +*/ diff --git a/src/improper_hybrid.cpp b/src/improper_hybrid.cpp new file mode 100644 index 000000000..9212051e3 --- /dev/null +++ b/src/improper_hybrid.cpp @@ -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. +------------------------------------------------------------------------- */ + +#include "math.h" +#include "string.h" +#include "ctype.h" +#include "improper_hybrid.h" +#include "atom.h" +#include "neighbor.h" +#include "domain.h" +#include "comm.h" +#include "force.h" +#include "memory.h" +#include "error.h" + +using namespace LAMMPS_NS; + +#define EXTRA 1000 + +/* ---------------------------------------------------------------------- */ + +ImproperHybrid::ImproperHybrid(LAMMPS *lmp) : Improper(lmp) +{ + nstyles = 0; +} + +/* ---------------------------------------------------------------------- */ + +ImproperHybrid::~ImproperHybrid() +{ + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] nimproperlist; + delete [] maximproper; + for (int i = 0; i < nstyles; i++) + memory->destroy(improperlist[i]); + delete [] improperlist; + } +} + +/* ---------------------------------------------------------------------- */ + +void ImproperHybrid::compute(int eflag, int vflag) +{ + int i,j,m,n; + + // save ptrs to original improperlist + + int nimproperlist_orig = neighbor->nimproperlist; + int **improperlist_orig = neighbor->improperlist; + + // if this is re-neighbor step, create sub-style improperlists + // nimproperlist[] = length of each sub-style list + // realloc sub-style improperlist if necessary + // load sub-style improperlist with 5 values from original improperlist + + if (neighbor->ago == 0) { + for (m = 0; m < nstyles; m++) nimproperlist[m] = 0; + for (i = 0; i < nimproperlist_orig; i++) { + m = map[improperlist_orig[i][4]]; + nimproperlist[m]++; + } + for (m = 0; m < nstyles; m++) { + if (nimproperlist[m] > maximproper[m]) { + memory->destroy(improperlist[m]); + maximproper[m] = nimproperlist[m] + EXTRA; + memory->create(improperlist[m],maximproper[m],5, + "improper_hybrid:improperlist"); + } + nimproperlist[m] = 0; + } + for (i = 0; i < nimproperlist_orig; i++) { + m = map[improperlist_orig[i][4]]; + if (m < 0) continue; + n = nimproperlist[m]; + improperlist[m][n][0] = improperlist_orig[i][0]; + improperlist[m][n][1] = improperlist_orig[i][1]; + improperlist[m][n][2] = improperlist_orig[i][2]; + improperlist[m][n][3] = improperlist_orig[i][3]; + improperlist[m][n][4] = improperlist_orig[i][4]; + nimproperlist[m]++; + } + } + + // call each sub-style's compute function + // set neighbor->improperlist to sub-style improperlist before call + // accumulate sub-style global/peratom energy/virial in hybrid + + if (eflag || vflag) ev_setup(eflag,vflag); + else evflag = 0; + + for (m = 0; m < nstyles; m++) { + neighbor->nimproperlist = nimproperlist[m]; + neighbor->improperlist = improperlist[m]; + + styles[m]->compute(eflag,vflag); + + if (eflag_global) energy += styles[m]->energy; + if (vflag_global) + for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n]; + if (eflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double *eatom_substyle = styles[m]->eatom; + for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i]; + } + if (vflag_atom) { + n = atom->nlocal; + if (force->newton_bond) n += atom->nghost; + double **vatom_substyle = styles[m]->vatom; + for (i = 0; i < n; i++) + for (j = 0; j < 6; j++) + vatom[i][j] += vatom_substyle[i][j]; + } + } + + // restore ptrs to original improperlist + + neighbor->nimproperlist = nimproperlist_orig; + neighbor->improperlist = improperlist_orig; +} + +/* ---------------------------------------------------------------------- */ + +void ImproperHybrid::allocate() +{ + allocated = 1; + int n = atom->nimpropertypes; + + memory->create(map,n+1,"improper:map"); + memory->create(setflag,n+1,"improper:setflag"); + for (int i = 1; i <= n; i++) setflag[i] = 0; + + nimproperlist = new int[nstyles]; + maximproper = new int[nstyles]; + improperlist = new int**[nstyles]; + for (int m = 0; m < nstyles; m++) maximproper[m] = 0; + for (int m = 0; m < nstyles; m++) improperlist[m] = NULL; +} + +/* ---------------------------------------------------------------------- + create one improper style for each arg in list +------------------------------------------------------------------------- */ + +void ImproperHybrid::settings(int narg, char **arg) +{ + int i,m,istyle; + + if (narg < 1) error->all(FLERR,"Illegal improper_style command"); + + // delete old lists, since cannot just change settings + + if (nstyles) { + for (int i = 0; i < nstyles; i++) delete styles[i]; + delete [] styles; + for (int i = 0; i < nstyles; i++) delete [] keywords[i]; + delete [] keywords; + } + + if (allocated) { + memory->destroy(setflag); + memory->destroy(map); + delete [] nimproperlist; + delete [] maximproper; + for (int i = 0; i < nstyles; i++) + memory->destroy(improperlist[i]); + delete [] improperlist; + } + allocated = 0; + + // count sub-styles by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric word + // need a better way to skip these exceptions + + nstyles = 0; + i = 0; + while (i < narg) { + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + nstyles++; + } + + // allocate list of sub-styles + + styles = new Improper*[nstyles]; + keywords = new char*[nstyles]; + + // allocate each sub-style and call its settings() with subset of args + // define subset of args for a sub-style by skipping numeric args + // one exception is 1st arg of style "table", which is non-numeric + // need a better way to skip these exceptions + + int dummy; + nstyles = 0; + i = 0; + + while (i < narg) { + for (m = 0; m < nstyles; m++) + if (strcmp(arg[i],keywords[m]) == 0) + error->all(FLERR,"Improper style hybrid cannot use " + "same improper style twice"); + if (strcmp(arg[i],"hybrid") == 0) + error->all(FLERR, + "Improper style hybrid cannot have hybrid as an argument"); + if (strcmp(arg[i],"none") == 0) + error->all(FLERR,"Improper style hybrid cannot have none as an argument"); + styles[nstyles] = force->new_improper(arg[i],lmp->suffix,dummy); + keywords[nstyles] = new char[strlen(arg[i])+1]; + strcpy(keywords[nstyles],arg[i]); + istyle = i; + if (strcmp(arg[i],"table") == 0) i++; + i++; + while (i < narg && !isalpha(arg[i][0])) i++; + styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]); + nstyles++; + } +} + +/* ---------------------------------------------------------------------- + set coeffs for one type +---------------------------------------------------------------------- */ + +void ImproperHybrid::coeff(int narg, char **arg) +{ + if (!allocated) allocate(); + + int ilo,ihi; + force->bounds(arg[0],atom->nimpropertypes,ilo,ihi); + + // 2nd arg = improper sub-style name + // allow for "none" as valid sub-style name + + int m; + for (m = 0; m < nstyles; m++) + if (strcmp(arg[1],keywords[m]) == 0) break; + + int none = 0; + if (m == nstyles) { + if (strcmp(arg[1],"none") == 0) none = 1; + else error->all(FLERR,"Improper coeff for hybrid has invalid style"); + } + + // move 1st arg to 2nd arg + // just copy ptrs, since arg[] points into original input line + + arg[1] = arg[0]; + + // invoke sub-style coeff() starting with 1st arg + + if (!none) styles[m]->coeff(narg-1,&arg[1]); + + // set setflag and which type maps to which sub-style + // if sub-style is none: set hybrid setflag, wipe out map + + for (int i = ilo; i <= ihi; i++) { + if (none) { + setflag[i] = 1; + map[i] = -1; + } else { + setflag[i] = styles[m]->setflag[i]; + map[i] = m; + } + } +} + +/* ---------------------------------------------------------------------- + proc 0 writes to restart file +------------------------------------------------------------------------- */ + +void ImproperHybrid::write_restart(FILE *fp) +{ + fwrite(&nstyles,sizeof(int),1,fp); + + int n; + for (int m = 0; m < nstyles; m++) { + n = strlen(keywords[m]) + 1; + fwrite(&n,sizeof(int),1,fp); + fwrite(keywords[m],sizeof(char),n,fp); + } +} + +/* ---------------------------------------------------------------------- + proc 0 reads from restart file, bcasts +------------------------------------------------------------------------- */ + +void ImproperHybrid::read_restart(FILE *fp) +{ + int me = comm->me; + if (me == 0) fread(&nstyles,sizeof(int),1,fp); + MPI_Bcast(&nstyles,1,MPI_INT,0,world); + styles = new Improper*[nstyles]; + keywords = new char*[nstyles]; + + allocate(); + + int n,dummy; + for (int m = 0; m < nstyles; m++) { + if (me == 0) fread(&n,sizeof(int),1,fp); + MPI_Bcast(&n,1,MPI_INT,0,world); + keywords[m] = new char[n]; + if (me == 0) fread(keywords[m],sizeof(char),n,fp); + MPI_Bcast(keywords[m],n,MPI_CHAR,0,world); + styles[m] = force->new_improper(keywords[m],lmp->suffix,dummy); + } +} + +/* ---------------------------------------------------------------------- + memory usage +------------------------------------------------------------------------- */ + +double ImproperHybrid::memory_usage() +{ + double bytes = maxeatom * sizeof(double); + bytes += maxvatom*6 * sizeof(double); + for (int m = 0; m < nstyles; m++) bytes += maximproper[m]*5 * sizeof(int); + for (int m = 0; m < nstyles; m++) + if (styles[m]) bytes += styles[m]->memory_usage(); + return bytes; +} diff --git a/src/improper_hybrid.h b/src/improper_hybrid.h new file mode 100644 index 000000000..aff04e09f --- /dev/null +++ b/src/improper_hybrid.h @@ -0,0 +1,84 @@ +/* ---------------------------------------------------------------------- + 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(hybrid,ImproperHybrid) + +#else + +#ifndef LMP_IMPROPER_HYBRID_H +#define LMP_IMPROPER_HYBRID_H + +#include "stdio.h" +#include "improper.h" + +namespace LAMMPS_NS { + +class ImproperHybrid : public Improper { + public: + int nstyles; // # of different improper styles + Improper **styles; // class list for each Improper style + char **keywords; // keyword for each improper style + + ImproperHybrid(class LAMMPS *); + ~ImproperHybrid(); + void compute(int, int); + void settings(int, char **); + void coeff(int, char **); + void write_restart(FILE *); + void read_restart(FILE *); + double memory_usage(); + + private: + int *map; // which style each improper type points to + + int *nimproperlist; // # of impropers in sub-style improperlists + int *maximproper; // max # of impropers sub-style lists can store + int ***improperlist; // improperlist for each sub-style + + void allocate(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Improper style hybrid cannot use same improper style twice + +Self-explanatory. + +E: Improper style hybrid cannot have hybrid as an argument + +Self-explanatory. + +E: Improper style hybrid cannot have none as an argument + +Self-explanatory. + +E: Improper coeff for hybrid has invalid style + +Improper style hybrid uses another improper style as one of its +coefficients. The improper style used in the improper_coeff command +or read from a restart file is not recognized. + +*/