diff --git a/doc/src/Manual.txt b/doc/src/Manual.txt index 5677d09a8..25319570a 100644 --- a/doc/src/Manual.txt +++ b/doc/src/Manual.txt @@ -1,340 +1,340 @@ LAMMPS Users Manual - + "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c :link(lws,http://lammps.sandia.gov) :link(ld,Manual.html) :link(lc,Section_commands.html#comm) :line

LAMMPS Documentation :c,h3 -20 Jan 2017 version :c,h4 +26 Jan 2017 version :c,h4 Version info: :h4 The LAMMPS "version" is the date when it was released, such as 1 May 2010. LAMMPS is updated continuously. Whenever we fix a bug or add a feature, we release it immediately, and post a notice on "this page of the WWW site"_bug. Every 2-4 months one of the incremental releases is subjected to more thorough testing and labeled as a {stable} version. Each dated copy of LAMMPS contains all the features and bug-fixes up to and including that version date. The version date is printed to the screen and logfile every time you run LAMMPS. It is also in the file src/version.h and in the LAMMPS directory name created when you unpack a tarball, and at the top of the first page of the manual (this page). If you browse the HTML doc pages on the LAMMPS WWW site, they always describe the most current version of LAMMPS. :ulb,l If you browse the HTML doc pages included in your tarball, they describe the version you have. :l The "PDF file"_Manual.pdf on the WWW site or in the tarball is updated about once per month. This is because it is large, and we don't want it to be part of every patch. :l There is also a "Developer.pdf"_Developer.pdf file in the doc directory, which describes the internal structure and algorithms of LAMMPS. :l :ule LAMMPS stands for Large-scale Atomic/Molecular Massively Parallel Simulator. LAMMPS is a classical molecular dynamics simulation code designed to run efficiently on parallel computers. It was developed at Sandia National Laboratories, a US Department of Energy facility, with funding from the DOE. It is an open-source code, distributed freely under the terms of the GNU Public License (GPL). The current core group of LAMMPS developers is at Sandia National Labs and Temple University: "Steve Plimpton"_sjp, sjplimp at sandia.gov :ulb,l Aidan Thompson, athomps at sandia.gov :l Stan Moore, stamoore at sandia.gov :l "Axel Kohlmeyer"_ako, akohlmey at gmail.com :l :ule Past core developers include Paul Crozier, Ray Shan and Mark Stevens, all at Sandia. The [LAMMPS home page] at "http://lammps.sandia.gov"_http://lammps.sandia.gov has more information about the code and its uses. Interaction with external LAMMPS developers, bug reports and feature requests are mainly coordinated through the "LAMMPS project on GitHub."_https://github.com/lammps/lammps The lammps.org domain, currently hosting "public continuous integration testing"_https://ci.lammps.org/job/lammps/ and "precompiled Linux RPM and Windows installer packages"_http://rpm.lammps.org is located at Temple University and managed by Richard Berger, richard.berger at temple.edu. :link(bug,http://lammps.sandia.gov/bug.html) :link(sjp,http://www.sandia.gov/~sjplimp) :link(ako,http://goo.gl/1wk0) :line The LAMMPS documentation is organized into the following sections. If you find errors or omissions in this manual or have suggestions for useful information to add, please send an email to the developers so we can improve the LAMMPS documentation. Once you are familiar with LAMMPS, you may want to bookmark "this page"_Section_commands.html#comm at Section_commands.html#comm since it gives quick access to documentation for all LAMMPS commands. "PDF file"_Manual.pdf of the entire manual, generated by "htmldoc"_http://freecode.com/projects/htmldoc "Introduction"_Section_intro.html :olb,l 1.1 "What is LAMMPS"_intro_1 :ulb,b 1.2 "LAMMPS features"_intro_2 :b 1.3 "LAMMPS non-features"_intro_3 :b 1.4 "Open source distribution"_intro_4 :b 1.5 "Acknowledgments and citations"_intro_5 :ule,b "Getting started"_Section_start.html :l 2.1 "What's in the LAMMPS distribution"_start_1 :ulb,b 2.2 "Making LAMMPS"_start_2 :b 2.3 "Making LAMMPS with optional packages"_start_3 :b 2.4 "Building LAMMPS via the Make.py script"_start_4 :b 2.5 "Building LAMMPS as a library"_start_5 :b 2.6 "Running LAMMPS"_start_6 :b 2.7 "Command-line options"_start_7 :b 2.8 "Screen output"_start_8 :b 2.9 "Tips for users of previous versions"_start_9 :ule,b "Commands"_Section_commands.html :l 3.1 "LAMMPS input script"_cmd_1 :ulb,b 3.2 "Parsing rules"_cmd_2 :b 3.3 "Input script structure"_cmd_3 :b 3.4 "Commands listed by category"_cmd_4 :b 3.5 "Commands listed alphabetically"_cmd_5 :ule,b "Packages"_Section_packages.html :l 4.1 "Standard packages"_pkg_1 :ulb,b 4.2 "User packages"_pkg_2 :ule,b "Accelerating LAMMPS performance"_Section_accelerate.html :l 5.1 "Measuring performance"_acc_1 :ulb,b 5.2 "Algorithms and code options to boost performace"_acc_2 :b 5.3 "Accelerator packages with optimized styles"_acc_3 :b 5.3.1 "GPU package"_accelerate_gpu.html :ulb,b 5.3.2 "USER-INTEL package"_accelerate_intel.html :b 5.3.3 "KOKKOS package"_accelerate_kokkos.html :b 5.3.4 "USER-OMP package"_accelerate_omp.html :b 5.3.5 "OPT package"_accelerate_opt.html :ule,b 5.4 "Comparison of various accelerator packages"_acc_4 :ule,b "How-to discussions"_Section_howto.html :l 6.1 "Restarting a simulation"_howto_1 :ulb,b 6.2 "2d simulations"_howto_2 :b 6.3 "CHARMM and AMBER force fields"_howto_3 :b 6.4 "Running multiple simulations from one input script"_howto_4 :b 6.5 "Multi-replica simulations"_howto_5 :b 6.6 "Granular models"_howto_6 :b 6.7 "TIP3P water model"_howto_7 :b 6.8 "TIP4P water model"_howto_8 :b 6.9 "SPC water model"_howto_9 :b 6.10 "Coupling LAMMPS to other codes"_howto_10 :b 6.11 "Visualizing LAMMPS snapshots"_howto_11 :b 6.12 "Triclinic (non-orthogonal) simulation boxes"_howto_12 :b 6.13 "NEMD simulations"_howto_13 :b 6.14 "Finite-size spherical and aspherical particles"_howto_14 :b 6.15 "Output from LAMMPS (thermo, dumps, computes, fixes, variables)"_howto_15 :b 6.16 "Thermostatting, barostatting, and compute temperature"_howto_16 :b 6.17 "Walls"_howto_17 :b 6.18 "Elastic constants"_howto_18 :b 6.19 "Library interface to LAMMPS"_howto_19 :b 6.20 "Calculating thermal conductivity"_howto_20 :b 6.21 "Calculating viscosity"_howto_21 :b 6.22 "Calculating a diffusion coefficient"_howto_22 :b 6.23 "Using chunks to calculate system properties"_howto_23 :b 6.24 "Setting parameters for pppm/disp"_howto_24 :b 6.25 "Polarizable models"_howto_25 :b 6.26 "Adiabatic core/shell model"_howto_26 :b 6.27 "Drude induced dipoles"_howto_27 :ule,b "Example problems"_Section_example.html :l "Performance & scalability"_Section_perf.html :l "Additional tools"_Section_tools.html :l "Modifying & extending LAMMPS"_Section_modify.html :l 10.1 "Atom styles"_mod_1 :ulb,b 10.2 "Bond, angle, dihedral, improper potentials"_mod_2 :b 10.3 "Compute styles"_mod_3 :b 10.4 "Dump styles"_mod_4 :b 10.5 "Dump custom output options"_mod_5 :b 10.6 "Fix styles"_mod_6 :b 10.7 "Input script commands"_mod_7 :b 10.8 "Kspace computations"_mod_8 :b 10.9 "Minimization styles"_mod_9 :b 10.10 "Pairwise potentials"_mod_10 :b 10.11 "Region styles"_mod_11 :b 10.12 "Body styles"_mod_12 :b 10.13 "Thermodynamic output options"_mod_13 :b 10.14 "Variable options"_mod_14 :b 10.15 "Submitting new features for inclusion in LAMMPS"_mod_15 :ule,b "Python interface"_Section_python.html :l 11.1 "Overview of running LAMMPS from Python"_py_1 :ulb,b 11.2 "Overview of using Python from a LAMMPS script"_py_2 :b 11.3 "Building LAMMPS as a shared library"_py_3 :b 11.4 "Installing the Python wrapper into Python"_py_4 :b 11.5 "Extending Python with MPI to run in parallel"_py_5 :b 11.6 "Testing the Python-LAMMPS interface"_py_6 :b 11.7 "Using LAMMPS from Python"_py_7 :b 11.8 "Example Python scripts that use LAMMPS"_py_8 :ule,b "Errors"_Section_errors.html :l 12.1 "Common problems"_err_1 :ulb,b 12.2 "Reporting bugs"_err_2 :b 12.3 "Error & warning messages"_err_3 :ule,b "Future and history"_Section_history.html :l 13.1 "Coming attractions"_hist_1 :ulb,b 13.2 "Past versions"_hist_2 :ule,b :ole :link(intro_1,Section_intro.html#intro_1) :link(intro_2,Section_intro.html#intro_2) :link(intro_3,Section_intro.html#intro_3) :link(intro_4,Section_intro.html#intro_4) :link(intro_5,Section_intro.html#intro_5) :link(start_1,Section_start.html#start_1) :link(start_2,Section_start.html#start_2) :link(start_3,Section_start.html#start_3) :link(start_4,Section_start.html#start_4) :link(start_5,Section_start.html#start_5) :link(start_6,Section_start.html#start_6) :link(start_7,Section_start.html#start_7) :link(start_8,Section_start.html#start_8) :link(start_9,Section_start.html#start_9) :link(cmd_1,Section_commands.html#cmd_1) :link(cmd_2,Section_commands.html#cmd_2) :link(cmd_3,Section_commands.html#cmd_3) :link(cmd_4,Section_commands.html#cmd_4) :link(cmd_5,Section_commands.html#cmd_5) :link(pkg_1,Section_packages.html#pkg_1) :link(pkg_2,Section_packages.html#pkg_2) :link(acc_1,Section_accelerate.html#acc_1) :link(acc_2,Section_accelerate.html#acc_2) :link(acc_3,Section_accelerate.html#acc_3) :link(acc_4,Section_accelerate.html#acc_4) :link(howto_1,Section_howto.html#howto_1) :link(howto_2,Section_howto.html#howto_2) :link(howto_3,Section_howto.html#howto_3) :link(howto_4,Section_howto.html#howto_4) :link(howto_5,Section_howto.html#howto_5) :link(howto_6,Section_howto.html#howto_6) :link(howto_7,Section_howto.html#howto_7) :link(howto_8,Section_howto.html#howto_8) :link(howto_9,Section_howto.html#howto_9) :link(howto_10,Section_howto.html#howto_10) :link(howto_11,Section_howto.html#howto_11) :link(howto_12,Section_howto.html#howto_12) :link(howto_13,Section_howto.html#howto_13) :link(howto_14,Section_howto.html#howto_14) :link(howto_15,Section_howto.html#howto_15) :link(howto_16,Section_howto.html#howto_16) :link(howto_17,Section_howto.html#howto_17) :link(howto_18,Section_howto.html#howto_18) :link(howto_19,Section_howto.html#howto_19) :link(howto_20,Section_howto.html#howto_20) :link(howto_21,Section_howto.html#howto_21) :link(howto_22,Section_howto.html#howto_22) :link(howto_23,Section_howto.html#howto_23) :link(howto_24,Section_howto.html#howto_24) :link(howto_25,Section_howto.html#howto_25) :link(howto_26,Section_howto.html#howto_26) :link(howto_27,Section_howto.html#howto_27) :link(mod_1,Section_modify.html#mod_1) :link(mod_2,Section_modify.html#mod_2) :link(mod_3,Section_modify.html#mod_3) :link(mod_4,Section_modify.html#mod_4) :link(mod_5,Section_modify.html#mod_5) :link(mod_6,Section_modify.html#mod_6) :link(mod_7,Section_modify.html#mod_7) :link(mod_8,Section_modify.html#mod_8) :link(mod_9,Section_modify.html#mod_9) :link(mod_10,Section_modify.html#mod_10) :link(mod_11,Section_modify.html#mod_11) :link(mod_12,Section_modify.html#mod_12) :link(mod_13,Section_modify.html#mod_13) :link(mod_14,Section_modify.html#mod_14) :link(mod_15,Section_modify.html#mod_15) :link(py_1,Section_python.html#py_1) :link(py_2,Section_python.html#py_2) :link(py_3,Section_python.html#py_3) :link(py_4,Section_python.html#py_4) :link(py_5,Section_python.html#py_5) :link(py_6,Section_python.html#py_6) :link(err_1,Section_errors.html#err_1) :link(err_2,Section_errors.html#err_2) :link(err_3,Section_errors.html#err_3) :link(hist_1,Section_history.html#hist_1) :link(hist_2,Section_history.html#hist_2) diff --git a/potentials/WL.meam b/potentials/WL.meam new file mode 100644 index 000000000..43eecb422 --- /dev/null +++ b/potentials/WL.meam @@ -0,0 +1,13 @@ +# DATE: 2017-01-25 CONTRIBUTOR: Aidan Thompson, athomps@sandia.gov, CITATION: Lee, Baskes, Kim, Cho. Phys. Rev. B, 64, 184102 (2001) +rc = 3.8 +delr = 0.1 +augt1 = 0 +erose_form = 2 +zbl(1,1) = 0 +nn2(1,1) = 1 +Ec(1,1) = 8.66 +re(1,1) = 2.74 +attrac(1,1) = 0 +repuls(1,1) = 0 +Cmin(1,1,1) = 0.49 +Cmax(1,1,1) = 2.8 diff --git a/src/angle_hybrid.cpp b/src/angle_hybrid.cpp index a477d7f8f..9b3af1856 100644 --- a/src/angle_hybrid.cpp +++ b/src/angle_hybrid.cpp @@ -1,376 +1,376 @@ /* ---------------------------------------------------------------------- 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 #include #include #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) { writedata = 0; 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; + else evflag = eflag_global = vflag_global = eflag_atom = vflag_atom = 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 // allocate uses suffix, but don't store suffix version in keywords, // else syntax in coeff() will not match // 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],1,dummy); force->store_style(keywords[nstyles],arg[i],0); 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(FLERR,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 if (strcmp(arg[1],"ba") == 0) error->all(FLERR,"BondAngle coeff for hybrid angle has invalid format"); else if (strcmp(arg[1],"bb") == 0) error->all(FLERR,"BondBond coeff for hybrid angle has invalid format"); 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],0,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/bond_hybrid.cpp b/src/bond_hybrid.cpp index 1244c2822..9a16d0e1f 100644 --- a/src/bond_hybrid.cpp +++ b/src/bond_hybrid.cpp @@ -1,362 +1,362 @@ /* ---------------------------------------------------------------------- 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 #include #include #include "bond_hybrid.h" #include "atom.h" #include "neighbor.h" #include "domain.h" #include "comm.h" #include "force.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; #define EXTRA 1000 /* ---------------------------------------------------------------------- */ BondHybrid::BondHybrid(LAMMPS *lmp) : Bond(lmp) { writedata = 0; nstyles = 0; } /* ---------------------------------------------------------------------- */ BondHybrid::~BondHybrid() { if (nstyles) { for (int i = 0; i < nstyles; i++) delete styles[i]; delete [] styles; for (int i = 0; i < nstyles; i++) delete [] keywords[i]; delete [] keywords; } if (allocated) { memory->destroy(setflag); memory->destroy(map); delete [] nbondlist; delete [] maxbond; for (int i = 0; i < nstyles; i++) memory->destroy(bondlist[i]); delete [] bondlist; } } /* ---------------------------------------------------------------------- */ void BondHybrid::compute(int eflag, int vflag) { int i,j,m,n; // save ptrs to original bondlist int nbondlist_orig = neighbor->nbondlist; int **bondlist_orig = neighbor->bondlist; // if this is re-neighbor step, create sub-style bondlists // nbondlist[] = length of each sub-style list // realloc sub-style bondlist if necessary // load sub-style bondlist with 3 values from original bondlist if (neighbor->ago == 0) { for (m = 0; m < nstyles; m++) nbondlist[m] = 0; for (i = 0; i < nbondlist_orig; i++) { m = map[bondlist_orig[i][2]]; if (m >= 0) nbondlist[m]++; } for (m = 0; m < nstyles; m++) { if (nbondlist[m] > maxbond[m]) { memory->destroy(bondlist[m]); maxbond[m] = nbondlist[m] + EXTRA; memory->create(bondlist[m],maxbond[m],3,"bond_hybrid:bondlist"); } nbondlist[m] = 0; } for (i = 0; i < nbondlist_orig; i++) { m = map[bondlist_orig[i][2]]; if (m < 0) continue; n = nbondlist[m]; bondlist[m][n][0] = bondlist_orig[i][0]; bondlist[m][n][1] = bondlist_orig[i][1]; bondlist[m][n][2] = bondlist_orig[i][2]; nbondlist[m]++; } } // call each sub-style's compute function // set neighbor->bondlist to sub-style bondlist before call // accumulate sub-style global/peratom energy/virial in hybrid if (eflag || vflag) ev_setup(eflag,vflag); - else evflag = 0; + else evflag = eflag_global = vflag_global = eflag_atom = vflag_atom = 0; for (m = 0; m < nstyles; m++) { neighbor->nbondlist = nbondlist[m]; neighbor->bondlist = bondlist[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 bondlist neighbor->nbondlist = nbondlist_orig; neighbor->bondlist = bondlist_orig; } /* ---------------------------------------------------------------------- */ void BondHybrid::allocate() { allocated = 1; int n = atom->nbondtypes; memory->create(map,n+1,"bond:map"); memory->create(setflag,n+1,"bond:setflag"); for (int i = 1; i <= n; i++) setflag[i] = 0; nbondlist = new int[nstyles]; maxbond = new int[nstyles]; bondlist = new int**[nstyles]; for (int m = 0; m < nstyles; m++) maxbond[m] = 0; for (int m = 0; m < nstyles; m++) bondlist[m] = NULL; } /* ---------------------------------------------------------------------- create one bond style for each arg in list ------------------------------------------------------------------------- */ void BondHybrid::settings(int narg, char **arg) { int i,m,istyle; if (narg < 1) error->all(FLERR,"Illegal bond_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 [] nbondlist; delete [] maxbond; for (int i = 0; i < nstyles; i++) memory->destroy(bondlist[i]); delete [] bondlist; } 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 Bond*[nstyles]; keywords = new char*[nstyles]; // allocate each sub-style and call its settings() with subset of args // allocate uses suffix, but don't store suffix version in keywords, // else syntax in coeff() will not match // 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,"Bond style hybrid cannot use same bond style twice"); if (strcmp(arg[i],"hybrid") == 0) error->all(FLERR,"Bond style hybrid cannot have hybrid as an argument"); if (strcmp(arg[i],"none") == 0) error->all(FLERR,"Bond style hybrid cannot have none as an argument"); styles[nstyles] = force->new_bond(arg[i],1,dummy); force->store_style(keywords[nstyles],arg[i],0); 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 BondHybrid::coeff(int narg, char **arg) { if (!allocated) allocate(); int ilo,ihi; force->bounds(FLERR,arg[0],atom->nbondtypes,ilo,ihi); // 2nd arg = bond 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,"Bond 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++) { setflag[i] = 1; if (none) map[i] = -1; else map[i] = m; } } /* ---------------------------------------------------------------------- */ void BondHybrid::init_style() { for (int m = 0; m < nstyles; m++) if (styles[m]) styles[m]->init_style(); } /* ---------------------------------------------------------------------- return an equilbrium bond length ------------------------------------------------------------------------- */ double BondHybrid::equilibrium_distance(int i) { if (map[i] < 0) error->one(FLERR,"Invoked bond equil distance on bond style none"); return styles[map[i]]->equilibrium_distance(i); } /* ---------------------------------------------------------------------- proc 0 writes to restart file ------------------------------------------------------------------------- */ void BondHybrid::write_restart(FILE *fp) { fwrite(&nstyles,sizeof(int),1,fp); int n; for (int m = 0; m < nstyles; m++) { n = strlen(keywords[m]) + 1; fwrite(&n,sizeof(int),1,fp); fwrite(keywords[m],sizeof(char),n,fp); } } /* ---------------------------------------------------------------------- proc 0 reads from restart file, bcasts ------------------------------------------------------------------------- */ void BondHybrid::read_restart(FILE *fp) { int me = comm->me; if (me == 0) fread(&nstyles,sizeof(int),1,fp); MPI_Bcast(&nstyles,1,MPI_INT,0,world); styles = new Bond*[nstyles]; keywords = new char*[nstyles]; 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_bond(keywords[m],0,dummy); } } /* ---------------------------------------------------------------------- */ double BondHybrid::single(int type, double rsq, int i, int j, double &fforce) { if (map[type] < 0) error->one(FLERR,"Invoked bond single on bond style none"); return styles[map[type]]->single(type,rsq,i,j,fforce); } /* ---------------------------------------------------------------------- memory usage ------------------------------------------------------------------------- */ double BondHybrid::memory_usage() { double bytes = maxeatom * sizeof(double); bytes += maxvatom*6 * sizeof(double); for (int m = 0; m < nstyles; m++) bytes += maxbond[m]*3 * sizeof(int); for (int m = 0; m < nstyles; m++) if (styles[m]) bytes += styles[m]->memory_usage(); return bytes; } diff --git a/src/dihedral_hybrid.cpp b/src/dihedral_hybrid.cpp index 0ae396b88..372a858d0 100644 --- a/src/dihedral_hybrid.cpp +++ b/src/dihedral_hybrid.cpp @@ -1,353 +1,353 @@ /* ---------------------------------------------------------------------- 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 #include #include #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; + else evflag = eflag_global = vflag_global = eflag_atom = vflag_atom = 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 // allocate uses suffix, but don't store suffix version in keywords, // else syntax in coeff() will not match // 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],1,dummy); force->store_style(keywords[nstyles],arg[i],0); 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(FLERR,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],0,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/improper_hybrid.cpp b/src/improper_hybrid.cpp index 78ee69569..abaaae02d 100644 --- a/src/improper_hybrid.cpp +++ b/src/improper_hybrid.cpp @@ -1,350 +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 #include #include #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]]; if (m >= 0) 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; + else evflag = eflag_global = vflag_global = eflag_atom = vflag_atom = 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; } /* ---------------------------------------------------------------------- */ void ImproperHybrid::init_style() { for (int i = 0; i < nstyles; i++) styles[i]->init_style(); } /* ---------------------------------------------------------------------- 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 // allocate uses suffix, but don't store suffix version in keywords, // else syntax in coeff() will not match // 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],1,dummy); force->store_style(keywords[nstyles],arg[i],0); 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(FLERR,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],0,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/neigh_request.cpp b/src/neigh_request.cpp index 6354af4d3..4007daadc 100644 --- a/src/neigh_request.cpp +++ b/src/neigh_request.cpp @@ -1,240 +1,245 @@ /* ---------------------------------------------------------------------- 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 "neigh_request.h" #include "atom.h" #include "memory.h" using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ NeighRequest::NeighRequest(LAMMPS *lmp) : Pointers(lmp) { // default ID = 0 id = 0; // class user of list: default is pair request // only one is set to 1 pair = 1; fix = compute = command = 0; // kind of list: default is half neighbor list // only one is set to 1 half = 1; full = 0; gran = granhistory = 0; respainner = respamiddle = respaouter = 0; half_from_full = 0; full_cluster = 0; // only set when command = 1; command_style = NULL; // combination of settings, mutiple can be set to 1 - // default is every reneighboring + // default is every reneighboring, not occasional // default is use newton_pair setting in force // default is no size history (when gran = 1) // default is no one-sided sphere/surface interactions (when gran = 1) // default is no auxiliary floating point values // default is no neighbors of ghosts // default is no multi-threaded neighbor list build // default is no Kokkos neighbor list build // default is no Shardlow Splitting Algorithm (SSA) neighbor list build + // default is neighbors of atoms, not bonds occasional = 0; newton = 0; granonesided = 0; dnum = 0; ghost = 0; omp = 0; intel = 0; kokkos_host = kokkos_device = 0; ssa = 0; + bond = 0; // copy/skip/derive info, default is no copy or skip // none or only one option is set copy = 0; skip = 0; iskip = NULL; ijskip = NULL; off2on = 0; otherlist = -1; } /* ---------------------------------------------------------------------- */ NeighRequest::~NeighRequest() { delete [] iskip; memory->destroy(ijskip); } /* ---------------------------------------------------------------------- archive request params that Neighbor may change after call to identical() ------------------------------------------------------------------------- */ void NeighRequest::archive() { half_original = half; half_from_full_original = half_from_full; copy_original = copy; otherlist_original = otherlist; } /* ---------------------------------------------------------------------- compare this request to other request identical means all params set by requestor are the same compare to original values in other if Neighbor may have changed them return 1 if identical, 0 if not ------------------------------------------------------------------------- */ int NeighRequest::identical(NeighRequest *other) { int same = 1; // set same = 0 if old list was never processed // use of requestor_instance and instance counter // prevents an old fix from being unfix/refix in same memory location // and appearing to be old, when it is really new // only needed for classes with persistent neigh lists: Fix, Compute, Pair if (requestor != other->requestor) same = 0; if (requestor_instance != other->requestor_instance) same = 0; if (id != other->id) same = 0; if (pair != other->pair) same = 0; if (fix != other->fix) same = 0; if (compute != other->compute) same = 0; if (command != other->command) same = 0; if (half != other->half_original) same = 0; if (full != other->full) same = 0; if (gran != other->gran) same = 0; if (respainner != other->respainner) same = 0; if (respamiddle != other->respamiddle) same = 0; if (respaouter != other->respaouter) same = 0; if (half_from_full != other->half_from_full_original) same = 0; if (newton != other->newton) same = 0; if (occasional != other->occasional) same = 0; if (granhistory != other->granhistory) same = 0; if (granonesided != other->granonesided) same = 0; if (dnum != other->dnum) same = 0; if (ghost != other->ghost) same = 0; if (omp != other->omp) same = 0; if (intel != other->intel) same = 0; if (kokkos_host != other->kokkos_host) same = 0; if (kokkos_device != other->kokkos_device) same = 0; if (ssa != other->ssa) same = 0; + if (bond != other->bond) same = 0; if (copy != other->copy_original) same = 0; if (same_skip(other) == 0) same = 0; if (otherlist != other->otherlist_original) same = 0; return same; } /* ---------------------------------------------------------------------- compare kind of this request to other request return 1 if same, 0 if different ------------------------------------------------------------------------- */ int NeighRequest::same_kind(NeighRequest *other) { int same = 1; // class caller will be same (pair), b/c called by pair hybrid styles // kind must be the the same if (half != other->half) same = 0; if (full != other->full) same = 0; if (gran != other->gran) same = 0; if (granhistory != other->granhistory) same = 0; if (respainner != other->respainner) same = 0; if (respamiddle != other->respamiddle) same = 0; if (respaouter != other->respaouter) same = 0; if (half_from_full != other->half_from_full) same = 0; // settings that must be the same // other settings do not need to be the same (e.g. granonesided) if (newton != other->newton) same = 0; if (ghost != other->ghost) same = 0; if (omp != other->omp) same = 0; if (intel != other->intel) same = 0; if (kokkos_host != other->kokkos_host) same = 0; if (kokkos_device != other->kokkos_device) same = 0; if (ssa != other->ssa) same = 0; + if (bond != other->bond) same = 0; // copy/skip/derive info does not need to be the same return same; } /* ---------------------------------------------------------------------- compare skip attributes of this request to other request return 1 if same, 0 if different ------------------------------------------------------------------------- */ int NeighRequest::same_skip(NeighRequest *other) { int i,j; int same = 1; if (skip != other->skip) same = 0; if (skip && other->skip) { int ntypes = atom->ntypes; for (i = 1; i <= ntypes; i++) if (iskip[i] != other->iskip[i]) same = 0; for (i = 1; i <= ntypes; i++) for (j = 1; j <= ntypes; j++) if (ijskip[i][j] != other->ijskip[i][j]) same = 0; } return same; } /* ---------------------------------------------------------------------- set kind and optional values in this request to those of other request not copy/skip/derive values since this may be non-skip parent of child ------------------------------------------------------------------------- */ void NeighRequest::copy_request(NeighRequest *other) { half = other->half; full = other->full; gran = other->gran; granhistory = other->granhistory; respainner = other->respainner; respamiddle = other->respamiddle; respaouter = other->respaouter; half_from_full = other->half_from_full; newton = other->newton; granonesided = other->granonesided; dnum = other->dnum; ghost = other->ghost; omp = other->omp; intel = other->intel; kokkos_host = other->kokkos_host; kokkos_device = other->kokkos_device; ssa = other->ssa; + bond = other->bond; } diff --git a/src/neigh_request.h b/src/neigh_request.h index 0b561710e..2738f4c03 100644 --- a/src/neigh_request.h +++ b/src/neigh_request.h @@ -1,139 +1,143 @@ /* -*- 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. ------------------------------------------------------------------------- */ #ifndef LMP_NEIGH_REQUEST_H #define LMP_NEIGH_REQUEST_H #include "pointers.h" namespace LAMMPS_NS { class NeighRequest : protected Pointers { public: int index; // index of which neigh request this is void *requestor; // class that made request int requestor_instance; // instance of that class (only Fix, Compute, Pair) int id; // ID of request as stored by requestor // used to track multiple requests from one class // which class style requests the list, one flag is 1, others are 0 int pair; // set by default int fix; int compute; int command; // kind of list requested, one flag is 1, others are 0 // NOTE: should make only the first 3 settings be unique, // allow others as add-on flags // this will require changed flags in pair requestors // this will lead to simpler logic in Neighbor::choose_build() int half; // 1 if half neigh list (set by default) int full; // 1 if full neigh list int half_from_full; // 1 if half list computed from previous full list int gran; // 1 if granular list int granhistory; // 1 if history info for granular contact pairs int respainner; // 1 if a rRESPA inner list int respamiddle; // 1 if a rRESPA middle list int respaouter; // 1 if a rRESPA outer list int full_cluster; // only used by Kokkos pair styles // command_style only set if command = 1 // allows print_pair_info() to access command name const char *command_style; // ----------------- // optional settings, set by caller, all are 0 by default // ----------------- // 0 if needed every reneighboring during run // 1 if occasionally needed by a fix, compute, etc int occasional; // 0 if use force::newton_pair setting // 1 if override with pair newton on // 2 if override with pair newton off int newton; // 1 if one-sided granular list for sphere/surf interactions (gran = 1) int granonesided; // number of auxiliary floating point values to store, 0 if none set int dnum; // 1 if also need neighbors of ghosts int ghost; // 1 if using multi-threaded neighbor list build for USER-OMP or USER-INTEL int omp; int intel; // 1 if using Kokkos neighbor build int kokkos_host; int kokkos_device; // 1 if using Shardlow Splitting Algorithm (SSA) neighbor list build int ssa; + // 1 if bond neighbors, not atom neighbors + + int bond; + // ----------------- // end of optional settings // ----------------- // set by pair_hybrid and neighbor after all requests are made // these settings do not change kind value or optional settings int copy; // 1 if this list copied from another list int skip; // 1 if this list skips atom types from another list int *iskip; // iskip[i] if atoms of type I are not in list int **ijskip; // ijskip[i][j] if pairs of type I,J are not in list int off2on; // 1 if this is newton on list, but skips from off list int otherlist; // index of other list to copy or skip from // original params by requestor // stored to compare against in identical() in case Neighbor changes them int half_original; int half_from_full_original; int copy_original; int otherlist_original; // pointer to FSH class, set by caller class FixShearHistory *fix_history; // fix that stores history info // methods NeighRequest(class LAMMPS *); ~NeighRequest(); void archive(); int identical(NeighRequest *); int same_kind(NeighRequest *); int same_skip(NeighRequest *); void copy_request(NeighRequest *); }; } #endif diff --git a/src/neighbor.cpp b/src/neighbor.cpp index cbcd5d640..79958a29f 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -1,2084 +1,2086 @@ /* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- Contributing author (triclinic and multi-neigh) : Pieter in 't Veld (SNL) ------------------------------------------------------------------------- */ #include #include #include #include #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "style_nbin.h" #include "style_nstencil.h" #include "style_npair.h" #include "style_ntopo.h" #include "atom.h" #include "atom_vec.h" #include "comm.h" #include "force.h" #include "pair.h" #include "domain.h" #include "group.h" #include "modify.h" #include "fix.h" #include "compute.h" #include "update.h" #include "respa.h" #include "output.h" #include "citeme.h" #include "memory.h" #include "error.h" #include using namespace LAMMPS_NS; using namespace NeighConst; #define RQDELTA 1 #define EXDELTA 1 #define BIG 1.0e20 enum{NSQ,BIN,MULTI}; // also in NBin, NeighList, NStencil enum{NONE,ALL,PARTIAL,TEMPLATE}; static const char cite_neigh_multi[] = "neighbor multi command:\n\n" "@Article{Intveld08,\n" " author = {P.{\\,}J.~in{\\,}'t~Veld and S.{\\,}J.~Plimpton" " and G.{\\,}S.~Grest},\n" " title = {Accurate and Efficient Methods for Modeling Colloidal\n" " Mixtures in an Explicit Solvent using Molecular Dynamics},\n" " journal = {Comp.~Phys.~Comm.},\n" " year = 2008,\n" " volume = 179,\n" " pages = {320--329}\n" "}\n\n"; //#define NEIGH_LIST_DEBUG 1 /* ---------------------------------------------------------------------- */ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp), pairclass(NULL), pairnames(NULL), pairmasks(NULL) { MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); firsttime = 1; style = BIN; every = 1; delay = 10; dist_check = 1; pgsize = 100000; oneatom = 2000; binsizeflag = 0; build_once = 0; cluster_check = 0; ago = -1; cutneighmax = 0.0; cutneighsq = NULL; cutneighghostsq = NULL; cuttype = NULL; cuttypesq = NULL; fixchecklist = NULL; // pairwise neighbor lists and associated data structs nlist = 0; lists = NULL; nbin = 0; neigh_bin = NULL; nstencil = 0; neigh_stencil = NULL; neigh_pair = NULL; nstencil_perpetual = 0; slist = NULL; npair_perpetual = 0; plist = NULL; nrequest = maxrequest = 0; requests = NULL; old_nrequest = 0; old_requests = NULL; old_style = style; old_triclinic = 0; old_pgsize = pgsize; old_oneatom = oneatom; zeroes = NULL; binclass = NULL; binnames = NULL; binmasks = NULL; stencilclass = NULL; stencilnames = NULL; stencilmasks = NULL; // topology lists bondwhich = anglewhich = dihedralwhich = improperwhich = NONE; neigh_bond = NULL; neigh_angle = NULL; neigh_dihedral = NULL; neigh_improper = NULL; // coords at last neighboring maxhold = 0; xhold = NULL; lastcall = -1; last_setup_bins = -1; // pair exclusion list info includegroup = 0; nex_type = maxex_type = 0; ex1_type = ex2_type = NULL; ex_type = NULL; nex_group = maxex_group = 0; ex1_group = ex2_group = ex1_bit = ex2_bit = NULL; nex_mol = maxex_mol = 0; ex_mol_group = ex_mol_bit = NULL; // Kokkos setting copymode = 0; } /* ---------------------------------------------------------------------- */ Neighbor::~Neighbor() { if (copymode) return; memory->destroy(cutneighsq); memory->destroy(cutneighghostsq); delete [] cuttype; delete [] cuttypesq; delete [] fixchecklist; for (int i = 0; i < nlist; i++) delete lists[i]; for (int i = 0; i < nbin; i++) delete neigh_bin[i]; for (int i = 0; i < nstencil; i++) delete neigh_stencil[i]; for (int i = 0; i < nlist; i++) delete neigh_pair[i]; delete [] lists; delete [] neigh_bin; delete [] neigh_stencil; delete [] neigh_pair; delete [] slist; delete [] plist; for (int i = 0; i < nrequest; i++) delete requests[i]; memory->sfree(requests); for (int i = 0; i < old_nrequest; i++) delete old_requests[i]; memory->sfree(old_requests); delete [] zeroes; delete [] binclass; delete [] binnames; delete [] binmasks; delete [] stencilclass; delete [] stencilnames; delete [] stencilmasks; delete [] pairclass; delete [] pairnames; delete [] pairmasks; delete neigh_bond; delete neigh_angle; delete neigh_dihedral; delete neigh_improper; memory->destroy(xhold); memory->destroy(ex1_type); memory->destroy(ex2_type); memory->destroy(ex_type); memory->destroy(ex1_group); memory->destroy(ex2_group); delete [] ex1_bit; delete [] ex2_bit; memory->destroy(ex_mol_group); delete [] ex_mol_bit; } /* ---------------------------------------------------------------------- */ void Neighbor::init() { int i,j,n; ncalls = ndanger = 0; dimension = domain->dimension; triclinic = domain->triclinic; newton_pair = force->newton_pair; // error check if (delay > 0 && (delay % every) != 0) error->all(FLERR,"Neighbor delay must be 0 or multiple of every setting"); if (pgsize < 10*oneatom) error->all(FLERR,"Neighbor page size must be >= 10x the one atom setting"); // ------------------------------------------------------------------ // settings // bbox lo/hi ptrs = bounding box of entire domain, stored by Domain if (triclinic == 0) { bboxlo = domain->boxlo; bboxhi = domain->boxhi; } else { bboxlo = domain->boxlo_bound; bboxhi = domain->boxhi_bound; } // set neighbor cutoffs (force cutoff + skin) // trigger determines when atoms migrate and neighbor lists are rebuilt // needs to be non-zero for migration distance check // even if pair = NULL and no neighbor lists are used // cutneigh = force cutoff + skin if cutforce > 0, else cutneigh = 0 // cutneighghost = pair cutghost if it requests it, else same as cutneigh triggersq = 0.25*skin*skin; boxcheck = 0; if (domain->box_change && (domain->xperiodic || domain->yperiodic || (dimension == 3 && domain->zperiodic))) boxcheck = 1; n = atom->ntypes; if (cutneighsq == NULL) { if (lmp->kokkos) init_cutneighsq_kokkos(n); else memory->create(cutneighsq,n+1,n+1,"neigh:cutneighsq"); memory->create(cutneighghostsq,n+1,n+1,"neigh:cutneighghostsq"); cuttype = new double[n+1]; cuttypesq = new double[n+1]; } double cutoff,delta,cut; cutneighmin = BIG; cutneighmax = 0.0; for (i = 1; i <= n; i++) { cuttype[i] = cuttypesq[i] = 0.0; for (j = 1; j <= n; j++) { if (force->pair) cutoff = sqrt(force->pair->cutsq[i][j]); else cutoff = 0.0; if (cutoff > 0.0) delta = skin; else delta = 0.0; cut = cutoff + delta; cutneighsq[i][j] = cut*cut; cuttype[i] = MAX(cuttype[i],cut); cuttypesq[i] = MAX(cuttypesq[i],cut*cut); cutneighmin = MIN(cutneighmin,cut); cutneighmax = MAX(cutneighmax,cut); if (force->pair && force->pair->ghostneigh) { cut = force->pair->cutghost[i][j] + skin; cutneighghostsq[i][j] = cut*cut; } else cutneighghostsq[i][j] = cut*cut; } } cutneighmaxsq = cutneighmax * cutneighmax; // rRESPA cutoffs int respa = 0; if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) { if (((Respa *) update->integrate)->level_inner >= 0) respa = 1; if (((Respa *) update->integrate)->level_middle >= 0) respa = 2; } if (respa) { double *cut_respa = ((Respa *) update->integrate)->cutoff; cut_inner_sq = (cut_respa[1] + skin) * (cut_respa[1] + skin); cut_middle_sq = (cut_respa[3] + skin) * (cut_respa[3] + skin); cut_middle_inside_sq = (cut_respa[0] - skin) * (cut_respa[0] - skin); if (cut_respa[0]-skin < 0) cut_middle_inside_sq = 0.0; } // fixchecklist = other classes that can induce reneighboring in decide() restart_check = 0; if (output->restart_flag) restart_check = 1; delete [] fixchecklist; fixchecklist = NULL; fixchecklist = new int[modify->nfix]; fix_check = 0; for (i = 0; i < modify->nfix; i++) if (modify->fix[i]->force_reneighbor) fixchecklist[fix_check++] = i; must_check = 0; if (restart_check || fix_check) must_check = 1; // set special_flag for 1-2, 1-3, 1-4 neighbors // flag[0] is not used, flag[1] = 1-2, flag[2] = 1-3, flag[3] = 1-4 // flag = 0 if both LJ/Coulomb special values are 0.0 // flag = 1 if both LJ/Coulomb special values are 1.0 // flag = 2 otherwise or if KSpace solver is enabled // pairwise portion of KSpace solver uses all 1-2,1-3,1-4 neighbors // or selected Coulomb-approixmation pair styles require it if (force->special_lj[1] == 0.0 && force->special_coul[1] == 0.0) special_flag[1] = 0; else if (force->special_lj[1] == 1.0 && force->special_coul[1] == 1.0) special_flag[1] = 1; else special_flag[1] = 2; if (force->special_lj[2] == 0.0 && force->special_coul[2] == 0.0) special_flag[2] = 0; else if (force->special_lj[2] == 1.0 && force->special_coul[2] == 1.0) special_flag[2] = 1; else special_flag[2] = 2; if (force->special_lj[3] == 0.0 && force->special_coul[3] == 0.0) special_flag[3] = 0; else if (force->special_lj[3] == 1.0 && force->special_coul[3] == 1.0) special_flag[3] = 1; else special_flag[3] = 2; if (force->kspace || force->pair_match("coul/wolf",0) || force->pair_match("coul/dsf",0) || force->pair_match("thole",0)) special_flag[1] = special_flag[2] = special_flag[3] = 2; // maxwt = max multiplicative factor on atom indices stored in neigh list maxwt = 0; if (special_flag[1] == 2) maxwt = 2; if (special_flag[2] == 2) maxwt = 3; if (special_flag[3] == 2) maxwt = 4; // ------------------------------------------------------------------ // xhold array // free if not needed for this run if (dist_check == 0) { memory->destroy(xhold); maxhold = 0; xhold = NULL; } // first time allocation if (dist_check) { if (maxhold == 0) { maxhold = atom->nmax; memory->create(xhold,maxhold,3,"neigh:xhold"); } } // ------------------------------------------------------------------ // exclusion lists // depend on type, group, molecule settings from neigh_modify // warn if exclusions used with KSpace solver n = atom->ntypes; if (nex_type == 0 && nex_group == 0 && nex_mol == 0) exclude = 0; else exclude = 1; if (nex_type) { if (lmp->kokkos) init_ex_type_kokkos(n); else { memory->destroy(ex_type); memory->create(ex_type,n+1,n+1,"neigh:ex_type"); } for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) ex_type[i][j] = 0; for (i = 0; i < nex_type; i++) { if (ex1_type[i] <= 0 || ex1_type[i] > n || ex2_type[i] <= 0 || ex2_type[i] > n) error->all(FLERR,"Invalid atom type in neighbor exclusion list"); ex_type[ex1_type[i]][ex2_type[i]] = 1; ex_type[ex2_type[i]][ex1_type[i]] = 1; } } if (nex_group) { if (lmp->kokkos) init_ex_bit_kokkos(); else { delete [] ex1_bit; delete [] ex2_bit; ex1_bit = new int[nex_group]; ex2_bit = new int[nex_group]; } for (i = 0; i < nex_group; i++) { ex1_bit[i] = group->bitmask[ex1_group[i]]; ex2_bit[i] = group->bitmask[ex2_group[i]]; } } if (nex_mol) { if (lmp->kokkos) init_ex_mol_bit_kokkos(); else { delete [] ex_mol_bit; ex_mol_bit = new int[nex_mol]; } for (i = 0; i < nex_mol; i++) ex_mol_bit[i] = group->bitmask[ex_mol_group[i]]; } if (exclude && force->kspace && me == 0) error->warning(FLERR,"Neighbor exclusions used with KSpace solver " "may give inconsistent Coulombic energies"); // ------------------------------------------------------------------ // create pairwise lists // one-time call to init_styles() to scan style files and setup // init_pair() creates auxiliary classes: NBin, NStencil, NPair if (firsttime) init_styles(); firsttime = 0; init_pair(); // invoke copy_neighbor_info() in Bin,Stencil,Pair classes // copied once per run in case any cutoff, exclusion, special info changed for (i = 0; i < nbin; i++) neigh_bin[i]->copy_neighbor_info(); for (i = 0; i < nstencil; i++) neigh_stencil[i]->copy_neighbor_info(); for (i = 0; i < nlist; i++) if (neigh_pair[i]) neigh_pair[i]->copy_neighbor_info(); if (!same && comm->me == 0) print_pairwise_info(); requests_new2old(); // ------------------------------------------------------------------ // create topology lists // instantiated topo styles can change from run to run init_topology(); } /* ---------------------------------------------------------------------- create and initialize lists of Nbin, Nstencil, NPair classes lists have info on all classes in 3 style*.h files cannot do this in constructor, b/c too early to instantiate classes ------------------------------------------------------------------------- */ void Neighbor::init_styles() { // extract info from NBin classes listed in style_nbin.h nbclass = 0; #define NBIN_CLASS #define NBinStyle(key,Class,bitmasks) nbclass++; #include "style_nbin.h" #undef NBinStyle #undef NBIN_CLASS binclass = new BinCreator[nbclass]; binnames = new char*[nbclass]; binmasks = new int[nbclass]; nbclass = 0; #define NBIN_CLASS #define NBinStyle(key,Class,bitmasks) \ binnames[nbclass] = (char *) #key; \ binclass[nbclass] = &bin_creator; \ binmasks[nbclass++] = bitmasks; #include "style_nbin.h" #undef NBinStyle #undef NBIN_CLASS // extract info from NStencil classes listed in style_nstencil.h nsclass = 0; #define NSTENCIL_CLASS #define NStencilStyle(key,Class,bitmasks) nsclass++; #include "style_nstencil.h" #undef NStencilStyle #undef NSTENCIL_CLASS stencilclass = new StencilCreator[nsclass]; stencilnames = new char*[nsclass]; stencilmasks = new int[nsclass]; nsclass = 0; #define NSTENCIL_CLASS #define NStencilStyle(key,Class,bitmasks) \ stencilnames[nsclass] = (char *) #key; \ stencilclass[nsclass] = &stencil_creator; \ stencilmasks[nsclass++] = bitmasks; #include "style_nstencil.h" #undef NStencilStyle #undef NSTENCIL_CLASS // extract info from NPair classes listed in style_npair.h npclass = 0; #define NPAIR_CLASS #define NPairStyle(key,Class,bitmasks) npclass++; #include "style_npair.h" #undef NPairStyle #undef NPAIR_CLASS pairclass = new PairCreator[npclass]; pairnames = new char*[npclass]; pairmasks = new int[npclass]; npclass = 0; #define NPAIR_CLASS #define NPairStyle(key,Class,bitmasks) \ pairnames[npclass] = (char *) #key; \ pairclass[npclass] = &pair_creator; \ pairmasks[npclass++] = bitmasks; #include "style_npair.h" #undef NPairStyle #undef NPAIR_CLASS } /* ---------------------------------------------------------------------- create and initialize NPair classes ------------------------------------------------------------------------- */ void Neighbor::init_pair() { int i,j,k,m; // test if pairwise lists need to be re-created // no need to re-create if: // neigh style, triclinic, pgsize, oneatom have not changed // current requests = old requests // first archive request params for current requests // before possibly changing them below for (i = 0; i < nrequest; i++) requests[i]->archive(); same = 1; if (style != old_style) same = 0; if (triclinic != old_triclinic) same = 0; if (pgsize != old_pgsize) same = 0; if (oneatom != old_oneatom) same = 0; if (nrequest != old_nrequest) same = 0; else for (i = 0; i < nrequest; i++) if (requests[i]->identical(old_requests[i]) == 0) same = 0; #ifdef NEIGH_LIST_DEBUG if (comm->me == 0) printf("SAME flag %d\n",same); #endif if (same) return; // delete old lists and create new ones for (i = 0; i < nlist; i++) delete lists[i]; for (i = 0; i < nbin; i++) delete neigh_bin[i]; for (i = 0; i < nstencil; i++) delete neigh_stencil[i]; for (i = 0; i < nlist; i++) delete neigh_pair[i]; delete [] lists; delete [] neigh_bin; delete [] neigh_stencil; delete [] neigh_pair; nlist = nrequest; lists = new NeighList*[nrequest]; neigh_bin = new NBin*[nrequest]; neigh_stencil = new NStencil*[nrequest]; neigh_pair = new NPair*[nrequest]; // create individual lists, one per request // pass list ptr back to requestor (except for Command class) // wait to allocate initial pages until copy lists are detected for (i = 0; i < nrequest; i++) { if (requests[i]->kokkos_host || requests[i]->kokkos_device) create_kokkos_list(i); else lists[i] = new NeighList(lmp); lists[i]->index = i; if (requests[i]->pair) { Pair *pair = (Pair *) requests[i]->requestor; pair->init_list(requests[i]->id,lists[i]); } else if (requests[i]->fix) { Fix *fix = (Fix *) requests[i]->requestor; fix->init_list(requests[i]->id,lists[i]); } else if (requests[i]->compute) { Compute *compute = (Compute *) requests[i]->requestor; compute->init_list(requests[i]->id,lists[i]); } } // morph requests via A,B,C rules // this is to avoid duplicate or inefficient builds // update both request and list when morph // (A) rule: // invoke post_constructor() for all lists // processes copy,skip,half_from_full,granhistory,respaouter lists // error checks and resets internal ptrs to other lists that now exist for (i = 0; i < nrequest; i++) lists[i]->post_constructor(requests[i]); // (B) rule: // if request = pair, half, newton != 2 // and full perpetual non-skip/copy list exists, // then morph to half_from_full of matching parent list // NOTE: should be OK if parent is skip list? // see build method comments // parent can be pair or fix, so long as perpetual fix // NOTE: could remove newton != 2 restriction if added // half_from_full_newtoff_ghost NPair class // this would require full list having ghost info // would be useful when reax/c used in hybrid mode, e.g. with airebo for (i = 0; i < nrequest; i++) { if (requests[i]->pair && requests[i]->half && requests[i]->newton != 2) { for (j = 0; j < nrequest; j++) { // Kokkos doesn't yet support half from full if (requests[i]->kokkos_device || requests[j]->kokkos_device) continue; if (requests[i]->kokkos_host || requests[j]->kokkos_host) continue; if (requests[j]->full && requests[j]->occasional == 0 && !requests[j]->skip && !requests[j]->copy) break; } if (j < nrequest) { requests[i]->half = 0; requests[i]->half_from_full = 1; lists[i]->listfull = lists[j]; } } } // (C) rule: // for fix/compute requests to be copied: // 1st check: // occasional or not does not matter // Kokkos host/device flags must match // SSA flag must match // newton setting must match (else list has different neighbors in it) // 2nd check: // if request = half and non-skip/copy pair half/respaouter request exists, // or if request = full and non-skip/copy pair full request exists, // or if request = gran and non-skip/copy pair gran request exists, // then morph to copy of the matching parent list // 3rd check: only if no match to 1st check // if request = half and non-skip/copy pair full request exists, // then morph to half_from_full of the matching parent list // for 1st or 2nd check, parent can be copy list or pair or fix int inewton,jnewton; for (i = 0; i < nrequest; i++) { if (!requests[i]->fix && !requests[i]->compute) continue; for (j = 0; j < nrequest; j++) { if (requests[i]->kokkos_device != requests[j]->kokkos_device) continue; if (requests[i]->kokkos_host != requests[j]->kokkos_host) continue; if (requests[i]->ssa != requests[j]->ssa) continue; // IJ newton = 1 for newton on, 2 for newton off inewton = requests[i]->newton; if (inewton == 0) inewton = force->newton_pair ? 1 : 2; jnewton = requests[j]->newton; if (jnewton == 0) jnewton = force->newton_pair ? 1 : 2; if (inewton != jnewton) continue; if (requests[i]->half && requests[j]->pair && !requests[j]->skip && requests[j]->half && !requests[j]->copy) break; if (requests[i]->half && requests[j]->pair && !requests[j]->skip && requests[j]->respaouter && !requests[j]->copy) break; if (requests[i]->full && requests[j]->pair && !requests[j]->skip && requests[j]->full && !requests[j]->copy) break; if (requests[i]->gran && requests[j]->pair && !requests[j]->skip && requests[j]->gran && !requests[j]->copy) break; } if (j < nrequest) { requests[i]->copy = 1; requests[i]->otherlist = j; lists[i]->copy = 1; lists[i]->listcopy = lists[j]; continue; } for (j = 0; j < nrequest; j++) { // Kokkos doesn't yet support half from full if (requests[i]->kokkos_device || requests[j]->kokkos_device) continue; if (requests[i]->kokkos_host || requests[j]->kokkos_host) continue; if (requests[i]->half && requests[j]->pair && !requests[j]->skip && requests[j]->full && !requests[j]->copy) break; } if (j < nrequest) { requests[i]->half = 0; requests[i]->half_from_full = 1; lists[i]->listfull = lists[j]; } } // assign Bin,Stencil,Pair style to each list int flag; for (i = 0; i < nrequest; i++) { flag = choose_bin(requests[i]); lists[i]->bin_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor bin option does not exist"); flag = choose_stencil(requests[i]); lists[i]->stencil_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor stencil method does not exist"); flag = choose_pair(requests[i]); lists[i]->pair_method = flag; if (flag < 0) error->all(FLERR,"Requested neighbor pair method does not exist"); } // instantiate unique Bin,Stencil classes in neigh_bin & neigh_stencil vecs // instantiate one Pair class per list in neigh_pair vec nbin = 0; for (i = 0; i < nrequest; i++) { flag = lists[i]->bin_method; if (flag == 0) continue; for (j = 0; j < nbin; j++) if (neigh_bin[j]->istyle == flag) break; if (j < nbin) continue; BinCreator bin_creator = binclass[flag-1]; neigh_bin[nbin] = bin_creator(lmp); neigh_bin[nbin]->istyle = flag; nbin++; } nstencil = 0; for (i = 0; i < nrequest; i++) { flag = lists[i]->stencil_method; if (flag == 0) continue; for (j = 0; j < nstencil; j++) if (neigh_stencil[j]->istyle == flag) break; if (j < nstencil) continue; StencilCreator stencil_creator = stencilclass[flag-1]; neigh_stencil[nstencil] = stencil_creator(lmp); neigh_stencil[nstencil]->istyle = flag; int bin_method = lists[i]->bin_method; for (k = 0; k < nbin; k++) { if (neigh_bin[k]->istyle == bin_method) { neigh_stencil[nstencil]->nb = neigh_bin[k]; break; } } if (k == nbin) error->all(FLERR,"Could not assign bin method to neighbor stencil"); nstencil++; } for (i = 0; i < nrequest; i++) { flag = lists[i]->pair_method; if (flag == 0) { neigh_pair[i] = NULL; continue; } PairCreator pair_creator = pairclass[flag-1]; neigh_pair[i] = pair_creator(lmp); neigh_pair[i]->istyle = flag; int bin_method = lists[i]->bin_method; if (bin_method == 0) neigh_pair[i]->nb = NULL; else { for (k = 0; k < nbin; k++) { if (neigh_bin[k]->istyle == bin_method) { neigh_pair[i]->nb = neigh_bin[k]; break; } } if (k == nbin) error->all(FLERR,"Could not assign bin method to neighbor pair"); } int stencil_method = lists[i]->stencil_method; if (stencil_method == 0) neigh_pair[i]->ns = NULL; else { for (k = 0; k < nstencil; k++) { if (neigh_stencil[k]->istyle == stencil_method) { neigh_pair[i]->ns = neigh_stencil[k]; break; } } if (k == nstencil) error->all(FLERR,"Could not assign stencil method to neighbor pair"); } } // allocate initial pages for each list, except if copy flag set // allocate dnum vector of zeroes if set int dnummax = 0; for (i = 0; i < nlist; i++) { if (lists[i]->copy) continue; lists[i]->setup_pages(pgsize,oneatom); dnummax = MAX(dnummax,lists[i]->dnum); } if (dnummax) { delete [] zeroes; zeroes = new double[dnummax]; for (i = 0; i < dnummax; i++) zeroes[i] = 0.0; } // first-time allocation of per-atom data for lists that are built and store // lists that are not built: granhistory, respa inner/middle (no neigh_pair) // lists that do not store: copy // use atom->nmax for both grow() args // i.e. grow first time to expanded size to avoid future reallocs // also Kokkos list initialization int maxatom = atom->nmax; for (i = 0; i < nlist; i++) if (neigh_pair[i] && !lists[i]->copy) lists[i]->grow(maxatom,maxatom); // plist = indices of perpetual NPair classes // perpetual = non-occasional, re-built at every reneighboring // slist = indices of perpetual NStencil classes // perpetual = used by any perpetual NPair class delete [] slist; delete [] plist; nstencil_perpetual = npair_perpetual = 0; slist = new int[nstencil]; plist = new int[nlist]; for (i = 0; i < nlist; i++) { if (lists[i]->occasional == 0 && lists[i]->pair_method) plist[npair_perpetual++] = i; } for (i = 0; i < nstencil; i++) { flag = 0; for (j = 0; j < npair_perpetual; j++) if (lists[plist[j]]->stencil_method == neigh_stencil[i]->istyle) flag = 1; if (flag) slist[nstencil_perpetual++] = i; } // reorder plist vector if necessary // relevant for lists that are derived from a parent list: // half-full,copy,skip // the child index must appear in plist after the parent index // swap two indices within plist when dependency is mis-ordered // start double loop check again whenever a swap is made // done when entire double loop test results in no swaps NeighList *ptr; int done = 0; while (!done) { done = 1; for (i = 0; i < npair_perpetual; i++) { for (k = 0; k < 3; k++) { ptr = NULL; if (k == 0) ptr = lists[plist[i]]->listcopy; if (k == 1) ptr = lists[plist[i]]->listskip; if (k == 2) ptr = lists[plist[i]]->listfull; if (ptr == NULL) continue; for (m = 0; m < nrequest; m++) if (ptr == lists[m]) break; for (j = 0; j < npair_perpetual; j++) if (m == plist[j]) break; if (j < i) continue; int tmp = plist[i]; // swap I,J indices plist[i] = plist[j]; plist[j] = tmp; done = 0; break; } if (!done) break; } } // debug output #ifdef NEIGH_LIST_DEBUG for (i = 0; i < nrequest; i++) lists[i]->print_attributes(); #endif } /* ---------------------------------------------------------------------- create and initialize NTopo classes ------------------------------------------------------------------------- */ void Neighbor::init_topology() { int i,m; if (!atom->molecular) return; // set flags that determine which topology neighbor classes to use // these settings could change from run to run, depending on fixes defined // bonds,etc can only be broken for atom->molecular = 1, not 2 // SHAKE sets bonds and angles negative // gcmc sets all bonds, angles, etc negative // bond_quartic sets bonds to 0 // delete_bonds sets all interactions negative int bond_off = 0; int angle_off = 0; for (i = 0; i < modify->nfix; i++) if ((strcmp(modify->fix[i]->style,"shake") == 0) || (strcmp(modify->fix[i]->style,"rattle") == 0)) bond_off = angle_off = 1; if (force->bond && force->bond_match("quartic")) bond_off = 1; if (atom->avec->bonds_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (bond_off) break; for (m = 0; m < atom->num_bond[i]; m++) if (atom->bond_type[i][m] <= 0) bond_off = 1; } } if (atom->avec->angles_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (angle_off) break; for (m = 0; m < atom->num_angle[i]; m++) if (atom->angle_type[i][m] <= 0) angle_off = 1; } } int dihedral_off = 0; if (atom->avec->dihedrals_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (dihedral_off) break; for (m = 0; m < atom->num_dihedral[i]; m++) if (atom->dihedral_type[i][m] <= 0) dihedral_off = 1; } } int improper_off = 0; if (atom->avec->impropers_allow && atom->molecular == 1) { for (i = 0; i < atom->nlocal; i++) { if (improper_off) break; for (m = 0; m < atom->num_improper[i]; m++) if (atom->improper_type[i][m] <= 0) improper_off = 1; } } for (i = 0; i < modify->nfix; i++) if ((strcmp(modify->fix[i]->style,"gcmc") == 0)) bond_off = angle_off = dihedral_off = improper_off = 1; // sync on/off settings across all procs int onoff = bond_off; MPI_Allreduce(&onoff,&bond_off,1,MPI_INT,MPI_MAX,world); onoff = angle_off; MPI_Allreduce(&onoff,&angle_off,1,MPI_INT,MPI_MAX,world); onoff = dihedral_off; MPI_Allreduce(&onoff,&dihedral_off,1,MPI_INT,MPI_MAX,world); onoff = improper_off; MPI_Allreduce(&onoff,&improper_off,1,MPI_INT,MPI_MAX,world); // instantiate NTopo classes if (atom->avec->bonds_allow) { int old_bondwhich = bondwhich; if (atom->molecular == 2) bondwhich = TEMPLATE; else if (bond_off) bondwhich = PARTIAL; else bondwhich = ALL; if (!neigh_bond || bondwhich != old_bondwhich) { delete neigh_bond; if (bondwhich == ALL) neigh_bond = new NTopoBondAll(lmp); else if (bondwhich == PARTIAL) neigh_bond = new NTopoBondPartial(lmp); else if (bondwhich == TEMPLATE) neigh_bond = new NTopoBondTemplate(lmp); } } if (atom->avec->angles_allow) { int old_anglewhich = anglewhich; if (atom->molecular == 2) anglewhich = TEMPLATE; else if (angle_off) anglewhich = PARTIAL; else anglewhich = ALL; if (!neigh_angle || anglewhich != old_anglewhich) { delete neigh_angle; if (anglewhich == ALL) neigh_angle = new NTopoAngleAll(lmp); else if (anglewhich == PARTIAL) neigh_angle = new NTopoAnglePartial(lmp); else if (anglewhich == TEMPLATE) neigh_angle = new NTopoAngleTemplate(lmp); } } if (atom->avec->dihedrals_allow) { int old_dihedralwhich = dihedralwhich; if (atom->molecular == 2) dihedralwhich = TEMPLATE; else if (dihedral_off) dihedralwhich = PARTIAL; else dihedralwhich = ALL; if (!neigh_dihedral || dihedralwhich != old_dihedralwhich) { delete neigh_dihedral; if (dihedralwhich == ALL) neigh_dihedral = new NTopoDihedralAll(lmp); else if (dihedralwhich == PARTIAL) neigh_dihedral = new NTopoDihedralPartial(lmp); else if (dihedralwhich == TEMPLATE) neigh_dihedral = new NTopoDihedralTemplate(lmp); } } if (atom->avec->impropers_allow) { int old_improperwhich = improperwhich; if (atom->molecular == 2) improperwhich = TEMPLATE; else if (improper_off) improperwhich = PARTIAL; else improperwhich = ALL; if (!neigh_improper || improperwhich != old_improperwhich) { delete neigh_improper; if (improperwhich == ALL) neigh_improper = new NTopoImproperAll(lmp); else if (improperwhich == PARTIAL) neigh_improper = new NTopoImproperPartial(lmp); else if (improperwhich == TEMPLATE) neigh_improper = new NTopoImproperTemplate(lmp); } } } /* ---------------------------------------------------------------------- output summary of pairwise neighbor list info only called by proc 0 ------------------------------------------------------------------------- */ void Neighbor::print_pairwise_info() { int i,m; char str[128]; const char *kind; FILE *out; const double cutghost = MAX(cutneighmax,comm->cutghostuser); double binsize, bbox[3]; bbox[0] = bboxhi[0]-bboxlo[0]; bbox[1] = bboxhi[1]-bboxlo[1]; bbox[2] = bboxhi[2]-bboxlo[2]; if (binsizeflag) binsize = binsize_user; else if (style == BIN) binsize = 0.5*cutneighmax; else binsize = 0.5*cutneighmin; if (binsize == 0.0) binsize = bbox[0]; int nperpetual = 0; int noccasional = 0; int nextra = 0; for (i = 0; i < nlist; i++) { if (lists[i]->pair_method == 0) nextra++; else if (lists[i]->occasional) noccasional++; else nperpetual++; } for (m = 0; m < 2; m++) { if (m == 0) out = screen; else out = logfile; if (out) { fprintf(out,"Neighbor list info ...\n"); fprintf(out," update every %d steps, delay %d steps, check %s\n", every,delay,dist_check ? "yes" : "no"); fprintf(out," max neighbors/atom: %d, page size: %d\n", oneatom, pgsize); fprintf(out," master list distance cutoff = %g\n",cutneighmax); fprintf(out," ghost atom cutoff = %g\n",cutghost); if (style != NSQ) fprintf(out," binsize = %g, bins = %g %g %g\n",binsize, ceil(bbox[0]/binsize), ceil(bbox[1]/binsize), ceil(bbox[2]/binsize)); fprintf(out," %d neighbor lists, " "perpetual/occasional/extra = %d %d %d\n", nlist,nperpetual,noccasional,nextra); for (i = 0; i < nlist; i++) { if (requests[i]->pair) { char *pname = force->pair_match_ptr((Pair *) requests[i]->requestor); sprintf(str," (%d) pair %s",i+1,pname); } else if (requests[i]->fix) { sprintf(str," (%d) fix %s",i+1, ((Fix *) requests[i]->requestor)->style); } else if (requests[i]->compute) { sprintf(str," (%d) compute %s",i+1, ((Compute *) requests[i]->requestor)->style); } else { sprintf(str," (%d) command %s",i+1,requests[i]->command_style); } fprintf(out,"%s",str); if (requests[i]->half) kind = "half"; else if (requests[i]->full) kind = "full"; else if (requests[i]->gran) kind = "size"; else if (requests[i]->granhistory) kind = "size/history"; else if (requests[i]->respainner) kind = "respa/inner"; else if (requests[i]->respamiddle) kind = "respa/middle"; else if (requests[i]->respaouter) kind = "respa/outer"; else if (requests[i]->half_from_full) kind = "half/from/full"; if (requests[i]->occasional) fprintf(out,", %s, occasional",kind); else fprintf(out,", %s, perpetual",kind); if (requests[i]->ghost) fprintf(out,", ghost"); if (requests[i]->ssa) fprintf(out,", ssa"); if (requests[i]->omp) fprintf(out,", omp"); if (requests[i]->intel) fprintf(out,", intel"); if (requests[i]->kokkos_device) fprintf(out,", kokkos_device"); if (requests[i]->kokkos_host) fprintf(out,", kokkos_host"); if (requests[i]->copy) fprintf(out,", copy from (%d)",requests[i]->otherlist+1); if (requests[i]->skip) fprintf(out,", skip from (%d)",requests[i]->otherlist+1); if (requests[i]->off2on) fprintf(out,", off2on"); fprintf(out,"\n"); if (lists[i]->pair_method == 0) fprintf(out," pair build: none\n"); else fprintf(out," pair build: %s\n", pairnames[lists[i]->pair_method-1]); if (lists[i]->stencil_method == 0) fprintf(out," stencil: none\n"); else fprintf(out," stencil: %s\n", stencilnames[lists[i]->stencil_method-1]); if (lists[i]->bin_method == 0) fprintf(out," bin: none\n"); else fprintf(out," bin: %s\n",binnames[lists[i]->bin_method-1]); } /* fprintf(out," %d stencil methods\n",nstencil); for (i = 0; i < nstencil; i++) fprintf(out," (%d) %s\n", i+1,stencilnames[neigh_stencil[i]->istyle-1]); fprintf(out," %d bin methods\n",nbin); for (i = 0; i < nbin; i++) fprintf(out," (%d) %s\n",i+1,binnames[neigh_bin[i]->istyle-1]); */ } } } /* ---------------------------------------------------------------------- delete old NeighRequests copy current requests and params to old for next run ------------------------------------------------------------------------- */ void Neighbor::requests_new2old() { for (int i = 0; i < old_nrequest; i++) delete old_requests[i]; memory->sfree(old_requests); old_nrequest = nrequest; old_requests = requests; nrequest = maxrequest = 0; requests = NULL; old_style = style; old_triclinic = triclinic; old_pgsize = pgsize; old_oneatom = oneatom; } /* ---------------------------------------------------------------------- assign NBin class to a NeighList use neigh request settings to build mask match mask to list of masks of known Nbin classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_bin(NeighRequest *rq) { // no binning needed if (style == NSQ) return 0; if (rq->skip || rq->copy || rq->half_from_full) return 0; if (rq->granhistory) return 0; if (rq->respainner || rq->respamiddle) return 0; // flags for settings the request + system requires of NBin class // ssaflag = no/yes ssa request // intelflag = no/yes intel request // kokkos_device_flag = no/yes kokkos device request // kokkos_host_flag = no/yes kokkos host request int ssaflag,intelflag,kokkos_device_flag,kokkos_host_flag; ssaflag = intelflag = kokkos_device_flag = kokkos_host_flag = 0; if (rq->ssa) ssaflag = NB_SSA; if (rq->intel) intelflag = NB_INTEL; if (rq->kokkos_device) kokkos_device_flag = NB_KOKKOS_DEVICE; if (rq->kokkos_host) kokkos_host_flag = NB_KOKKOS_HOST; // use flags to match exactly one of NBin class masks, bit by bit int mask; for (int i = 0; i < nbclass; i++) { mask = binmasks[i]; if (ssaflag != (mask & NB_SSA)) continue; if (intelflag != (mask & NB_INTEL)) continue; if (kokkos_device_flag != (mask & NB_KOKKOS_DEVICE)) continue; if (kokkos_host_flag != (mask & NB_KOKKOS_HOST)) continue; return i+1; } // error return if matched none return -1; } /* ---------------------------------------------------------------------- assign NStencil class to a NeighList use neigh request settings to build mask match mask to list of masks of known NStencil classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_stencil(NeighRequest *rq) { // no stencil creation needed if (style == NSQ) return 0; if (rq->skip || rq->copy || rq->half_from_full) return 0; if (rq->granhistory) return 0; if (rq->respainner || rq->respamiddle) return 0; // flags for settings the request + system requires of NStencil class // halfflag = half request (gran and respa are also half lists) // fullflag = full request // ghostflag = no/yes ghost request // ssaflag = no/yes ssa request // dimension = 2d/3d // newtflag = newton off/on request // triclinic = orthgonal/triclinic box int halfflag,fullflag,ghostflag,ssaflag; halfflag = fullflag = ghostflag = ssaflag = 0; if (rq->half) halfflag = 1; if (rq->full) fullflag = 1; if (rq->gran) halfflag = 1; if (rq->respaouter) halfflag = 1; if (rq->ghost) ghostflag = NS_GHOST; if (rq->ssa) ssaflag = NS_SSA; int newtflag; if (rq->newton == 0 && newton_pair) newtflag = 1; else if (rq->newton == 0 && !newton_pair) newtflag = 0; else if (rq->newton == 1) newtflag = 1; else if (rq->newton == 2) newtflag = 0; // use flags to match exactly one of NStencil class masks, bit by bit // exactly one of halfflag,fullflag is set and thus must match int mask; for (int i = 0; i < nsclass; i++) { mask = stencilmasks[i]; if (halfflag) { if (!(mask & NS_HALF)) continue; } else if (fullflag) { if (!(mask & NS_FULL)) continue; } if (ghostflag != (mask & NS_GHOST)) continue; if (ssaflag != (mask & NS_SSA)) continue; if (style == BIN && !(mask & NS_BIN)) continue; if (style == MULTI && !(mask & NS_MULTI)) continue; if (dimension == 2 && !(mask & NS_2D)) continue; if (dimension == 3 && !(mask & NS_3D)) continue; if (newtflag && !(mask & NS_NEWTON)) continue; if (!newtflag && !(mask & NS_NEWTOFF)) continue; if (!triclinic && !(mask & NS_ORTHO)) continue; if (triclinic && !(mask & NS_TRI)) continue; return i+1; } // error return if matched none return -1; } /* ---------------------------------------------------------------------- assign NPair class to a NeighList use neigh request settings to build mask match mask to list of masks of known NPair classes return index+1 of match in list of masks return 0 for no binning return -1 if no match ------------------------------------------------------------------------- */ int Neighbor::choose_pair(NeighRequest *rq) { // no NPair build performed if (rq->granhistory) return 0; if (rq->respainner || rq->respamiddle) return 0; // error check for includegroup with ghost neighbor request if (includegroup && rq->ghost) error->all(FLERR,"Neighbor include group not allowed " "with ghost neighbors"); // flags for settings the request + system requires of NPair class // some are set to 0/1, others are set to mask bit // comparisons below in loop over classes reflect that // copyflag = no/yes copy request // skipflag = no/yes skip request // halfflag = half request (gran and respa are also half lists) // fullflag = full request // halffullflag = half_from_full request // sizeflag = no/yes gran request for finite-size particles // ghostflag = no/yes ghost request // respaflag = no/yes respa request // off2onflag = no/yes off2on request // onesideflag = no/yes granonesided request // ssaflag = no/yes request // ompflag = no/yes omp request // intelflag = no/yes intel request // kokkos_device_flag = no/yes Kokkos device request // kokkos_host_flag = no/yes Kokkos host request // newtflag = newton off/on request // style = NSQ/BIN/MULTI neighbor style // triclinic = orthgonal/triclinic box int copyflag,skipflag,halfflag,fullflag,halffullflag,sizeflag,respaflag, ghostflag,off2onflag,onesideflag,ssaflag,ompflag,intelflag, - kokkos_device_flag,kokkos_host_flag; + kokkos_device_flag,kokkos_host_flag,bondflag; copyflag = skipflag = halfflag = fullflag = halffullflag = sizeflag = ghostflag = respaflag = off2onflag = onesideflag = ssaflag = - ompflag = intelflag = kokkos_device_flag = kokkos_host_flag = 0; + ompflag = intelflag = kokkos_device_flag = kokkos_host_flag = bondflag = 0; if (rq->copy) copyflag = NP_COPY; if (rq->skip) skipflag = NP_SKIP; // NOTE: exactly one of these request flags is set (see neigh_request.h) // this requires gran/respaouter also set halfflag // can simplify this logic, if follow NOTE in neigh_request.h // why do size/off2on and size/off2on/oneside set NP_HALF // either should set both half & full, or half should be in file name // to be consistent with how other NP classes use "half" if (rq->half) halfflag = 1; if (rq->full) fullflag = 1; if (rq->half_from_full) halffullflag = 1; if (rq->gran) { sizeflag = NP_SIZE; halfflag = 1; } if (rq->respaouter) { respaflag = NP_RESPA; halfflag = 1; } if (rq->ghost) ghostflag = NP_GHOST; if (rq->off2on) off2onflag = NP_OFF2ON; if (rq->granonesided) onesideflag = NP_ONESIDE; if (rq->ssa) ssaflag = NP_SSA; if (rq->omp) ompflag = NP_OMP; if (rq->intel) intelflag = NP_INTEL; if (rq->kokkos_device) kokkos_device_flag = NP_KOKKOS_DEVICE; if (rq->kokkos_host) kokkos_host_flag = NP_KOKKOS_HOST; + if (rq->bond) bondflag = NP_BOND; int newtflag; if (rq->newton == 0 && newton_pair) newtflag = 1; else if (rq->newton == 0 && !newton_pair) newtflag = 0; else if (rq->newton == 1) newtflag = 1; else if (rq->newton == 2) newtflag = 0; // use flags to match exactly one of NPair class masks // sequence of checks is bit by bit in NeighConst int mask; - //printf("FLAGS: %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + //printf("FLAGS: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", // copyflag,skipflag,halfflag,fullflag,halffullflag, // sizeflag,respaflag,ghostflag,off2onflag,onesideflag,ssaflag, - // ompflag,intelflag,newtflag); + // ompflag,intelflag,newtflag,bondflag); for (int i = 0; i < npclass; i++) { mask = pairmasks[i]; // if copyflag set, return or continue with no further checks if (copyflag) { if (!(mask & NP_COPY)) continue; if (kokkos_device_flag != (mask & NP_KOKKOS_DEVICE)) continue; if (kokkos_host_flag != (mask & NP_KOKKOS_HOST)) continue; return i+1; } // skipflag must match along with other flags, so do not return if (skipflag != (mask & NP_SKIP)) continue; // exactly one of halfflag,fullflag,halffullflag is set and must match if (halfflag) { if (!(mask & NP_HALF)) continue; } else if (fullflag) { if (!(mask & NP_FULL)) continue; } else if (halffullflag) { if (!(mask & NP_HALFFULL)) continue; } if (sizeflag != (mask & NP_SIZE)) continue; if (respaflag != (mask & NP_RESPA)) continue; if (ghostflag != (mask & NP_GHOST)) continue; if (off2onflag != (mask & NP_OFF2ON)) continue; if (onesideflag != (mask & NP_ONESIDE)) continue; if (ssaflag != (mask & NP_SSA)) continue; + if (bondflag != (mask & NP_BOND)) continue; if (ompflag != (mask & NP_OMP)) continue; if (intelflag != (mask & NP_INTEL)) continue; // style is one of NSQ,BIN,MULTI and must match if (style == NSQ) { if (!(mask & NP_NSQ)) continue; } else if (style == BIN) { if (!(mask & NP_BIN)) continue; } else if (style == MULTI) { if (!(mask & NP_MULTI)) continue; } // newtflag is on or off and must match if (newtflag) { if (!(mask & NP_NEWTON)) continue; } else if (!newtflag) { if (!(mask & NP_NEWTOFF)) continue; } // triclinic flag is on or off and must match if (triclinic) { if (!(mask & NP_TRI)) continue; } else if (!triclinic) { if (!(mask & NP_ORTHO)) continue; } // Kokkos flags if (kokkos_device_flag != (mask & NP_KOKKOS_DEVICE)) continue; if (kokkos_host_flag != (mask & NP_KOKKOS_HOST)) continue; return i+1; } //printf("NO MATCH\n"); // error return if matched none return -1; } /* ---------------------------------------------------------------------- called by other classes to request a pairwise neighbor list ------------------------------------------------------------------------- */ int Neighbor::request(void *requestor, int instance) { if (nrequest == maxrequest) { maxrequest += RQDELTA; requests = (NeighRequest **) memory->srealloc(requests,maxrequest*sizeof(NeighRequest *), "neighbor:requests"); } requests[nrequest] = new NeighRequest(lmp); requests[nrequest]->index = nrequest; requests[nrequest]->requestor = requestor; requests[nrequest]->requestor_instance = instance; nrequest++; return nrequest-1; } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_bin.h ------------------------------------------------------------------------- */ template NBin *Neighbor::bin_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_stencil.h ------------------------------------------------------------------------- */ template NStencil *Neighbor::stencil_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- one instance per entry in style_neigh_pair.h ------------------------------------------------------------------------- */ template NPair *Neighbor::pair_creator(LAMMPS *lmp) { return new T(lmp); } /* ---------------------------------------------------------------------- setup neighbor binning and neighbor stencils called before run and every reneighbor if box size/shape changes only operates on perpetual lists build_one() operates on occasional lists ------------------------------------------------------------------------- */ void Neighbor::setup_bins() { // invoke setup_bins() for all NBin // actual binning is performed in build() for (int i = 0; i < nbin; i++) neigh_bin[i]->setup_bins(style); // invoke create_setup() and create() for all perpetual NStencil // same ops performed for occasional lists in build_one() for (int i = 0; i < nstencil_perpetual; i++) { neigh_stencil[slist[i]]->create_setup(); neigh_stencil[slist[i]]->create(); } last_setup_bins = update->ntimestep; } /* ---------------------------------------------------------------------- */ int Neighbor::decide() { if (must_check) { bigint n = update->ntimestep; if (restart_check && n == output->next_restart) return 1; for (int i = 0; i < fix_check; i++) if (n == modify->fix[fixchecklist[i]]->next_reneighbor) return 1; } ago++; if (ago >= delay && ago % every == 0) { if (build_once) return 0; if (dist_check == 0) return 1; return check_distance(); } else return 0; } /* ---------------------------------------------------------------------- if any atom moved trigger distance (half of neighbor skin) return 1 shrink trigger distance if box size has changed conservative shrink procedure: compute distance each of 8 corners of box has moved since last reneighbor reduce skin distance by sum of 2 largest of the 8 values new trigger = 1/2 of reduced skin distance for orthogonal box, only need 2 lo/hi corners for triclinic, need all 8 corners since deformations can displace all 8 ------------------------------------------------------------------------- */ int Neighbor::check_distance() { double delx,dely,delz,rsq; double delta,deltasq,delta1,delta2; if (boxcheck) { if (triclinic == 0) { delx = bboxlo[0] - boxlo_hold[0]; dely = bboxlo[1] - boxlo_hold[1]; delz = bboxlo[2] - boxlo_hold[2]; delta1 = sqrt(delx*delx + dely*dely + delz*delz); delx = bboxhi[0] - boxhi_hold[0]; dely = bboxhi[1] - boxhi_hold[1]; delz = bboxhi[2] - boxhi_hold[2]; delta2 = sqrt(delx*delx + dely*dely + delz*delz); delta = 0.5 * (skin - (delta1+delta2)); deltasq = delta*delta; } else { domain->box_corners(); delta1 = delta2 = 0.0; for (int i = 0; i < 8; i++) { delx = corners[i][0] - corners_hold[i][0]; dely = corners[i][1] - corners_hold[i][1]; delz = corners[i][2] - corners_hold[i][2]; delta = sqrt(delx*delx + dely*dely + delz*delz); if (delta > delta1) delta1 = delta; else if (delta > delta2) delta2 = delta; } delta = 0.5 * (skin - (delta1+delta2)); deltasq = delta*delta; } } else deltasq = triggersq; double **x = atom->x; int nlocal = atom->nlocal; if (includegroup) nlocal = atom->nfirst; int flag = 0; for (int i = 0; i < nlocal; i++) { delx = x[i][0] - xhold[i][0]; dely = x[i][1] - xhold[i][1]; delz = x[i][2] - xhold[i][2]; rsq = delx*delx + dely*dely + delz*delz; if (rsq > deltasq) flag = 1; } int flagall; MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world); if (flagall && ago == MAX(every,delay)) ndanger++; return flagall; } /* ---------------------------------------------------------------------- build perpetual neighbor lists called at setup and every few timesteps during run or minimization topology lists also built if topoflag = 1 (Kokkos calls with topoflag=0) ------------------------------------------------------------------------- */ void Neighbor::build(int topoflag) { int i,m; ago = 0; ncalls++; lastcall = update->ntimestep; int nlocal = atom->nlocal; int nall = nlocal + atom->nghost; // check that using special bond flags will not overflow neigh lists if (nall > NEIGHMASK) error->one(FLERR,"Too many local+ghost atoms for neighbor list"); // store current atom positions and box size if needed if (dist_check) { double **x = atom->x; if (includegroup) nlocal = atom->nfirst; if (atom->nmax > maxhold) { maxhold = atom->nmax; memory->destroy(xhold); memory->create(xhold,maxhold,3,"neigh:xhold"); } for (i = 0; i < nlocal; i++) { xhold[i][0] = x[i][0]; xhold[i][1] = x[i][1]; xhold[i][2] = x[i][2]; } if (boxcheck) { if (triclinic == 0) { boxlo_hold[0] = bboxlo[0]; boxlo_hold[1] = bboxlo[1]; boxlo_hold[2] = bboxlo[2]; boxhi_hold[0] = bboxhi[0]; boxhi_hold[1] = bboxhi[1]; boxhi_hold[2] = bboxhi[2]; } else { domain->box_corners(); corners = domain->corners; for (i = 0; i < 8; i++) { corners_hold[i][0] = corners[i][0]; corners_hold[i][1] = corners[i][1]; corners_hold[i][2] = corners[i][2]; } } } } // bin atoms for all NBin instances // not just NBin associated with perpetual lists // b/c cannot wait to bin occasional lists in build_one() call // if bin then, atoms may have moved outside of proc domain & bin extent, // leading to errors or even a crash if (style != NSQ) { for (int i = 0; i < nbin; i++) { neigh_bin[i]->bin_atoms_setup(nall); neigh_bin[i]->bin_atoms(); } } // build pairwise lists for all perpetual NPair/NeighList // grow() with nlocal/nall args so that only realloc if have to for (i = 0; i < npair_perpetual; i++) { m = plist[i]; if (!lists[m]->copy) lists[m]->grow(nlocal,nall); neigh_pair[m]->build_setup(); neigh_pair[m]->build(lists[m]); } // build topology lists for bonds/angles/etc if (atom->molecular && topoflag) build_topology(); } /* ---------------------------------------------------------------------- build topology neighbor lists: bond, angle, dihedral, improper copy their list info back to Neighbor for access by bond/angle/etc classes ------------------------------------------------------------------------- */ void Neighbor::build_topology() { if (force->bond) { neigh_bond->build(); nbondlist = neigh_bond->nbondlist; bondlist = neigh_bond->bondlist; } if (force->angle) { neigh_angle->build(); nanglelist = neigh_angle->nanglelist; anglelist = neigh_angle->anglelist; } if (force->dihedral) { neigh_dihedral->build(); ndihedrallist = neigh_dihedral->ndihedrallist; dihedrallist = neigh_dihedral->dihedrallist; } if (force->improper) { neigh_improper->build(); nimproperlist = neigh_improper->nimproperlist; improperlist = neigh_improper->improperlist; } } /* ---------------------------------------------------------------------- build a single occasional pairwise neighbor list indexed by I called by other classes ------------------------------------------------------------------------- */ void Neighbor::build_one(class NeighList *mylist, int preflag) { // check if list structure is initialized if (mylist == NULL) error->all(FLERR,"Trying to build an occasional neighbor list " "before initialization completed"); // build_one() should never be invoked on a perpetual list if (!mylist->occasional) error->all(FLERR,"Neighbor build one invoked on perpetual list"); // no need to build if already built since last re-neighbor // preflag is set by fix bond/create and fix bond/swap // b/c they invoke build_one() on same step neigh list is re-built, // but before re-build, so need to use ">" instead of ">=" NPair *np = neigh_pair[mylist->index]; if (preflag) { if (np->last_build > lastcall) return; } else { if (np->last_build >= lastcall) return; } // if this is copy list and parent is occasional list, // or this is half_from_full and parent is occasional list, // insure parent is current if (mylist->listcopy && mylist->listcopy->occasional) build_one(mylist->listcopy,preflag); if (mylist->listfull && mylist->listfull->occasional) build_one(mylist->listfull,preflag); // create stencil if hasn't been created since last setup_bins() call NStencil *ns = np->ns; if (ns && ns->last_stencil < last_setup_bins) { ns->create_setup(); ns->create(); } // build the list np->build_setup(); np->build(mylist); } /* ---------------------------------------------------------------------- set neighbor style and skin distance ------------------------------------------------------------------------- */ void Neighbor::set(int narg, char **arg) { if (narg != 2) error->all(FLERR,"Illegal neighbor command"); skin = force->numeric(FLERR,arg[0]); if (skin < 0.0) error->all(FLERR,"Illegal neighbor command"); if (strcmp(arg[1],"nsq") == 0) style = NSQ; else if (strcmp(arg[1],"bin") == 0) style = BIN; else if (strcmp(arg[1],"multi") == 0) style = MULTI; else error->all(FLERR,"Illegal neighbor command"); if (style == MULTI && lmp->citeme) lmp->citeme->add(cite_neigh_multi); } /* ---------------------------------------------------------------------- reset timestamps in all NeignBin, NStencil, NPair classes so that neighbor lists will rebuild properly with timestep change ditto for lastcall and last_setup_bins ------------------------------------------------------------------------- */ void Neighbor::reset_timestep(bigint ntimestep) { for (int i = 0; i < nbin; i++) neigh_bin[i]->last_bin = -1; for (int i = 0; i < nstencil; i++) neigh_stencil[i]->last_stencil = -1; for (int i = 0; i < nlist; i++) { if (!neigh_pair[i]) continue; neigh_pair[i]->last_build = -1; } lastcall = -1; last_setup_bins = -1; } /* ---------------------------------------------------------------------- modify parameters of the pair-wise neighbor build ------------------------------------------------------------------------- */ void Neighbor::modify_params(int narg, char **arg) { int iarg = 0; while (iarg < narg) { if (strcmp(arg[iarg],"every") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); every = force->inumeric(FLERR,arg[iarg+1]); if (every <= 0) error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"delay") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); delay = force->inumeric(FLERR,arg[iarg+1]); if (delay < 0) error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"check") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) dist_check = 1; else if (strcmp(arg[iarg+1],"no") == 0) dist_check = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"once") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) build_once = 1; else if (strcmp(arg[iarg+1],"no") == 0) build_once = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"page") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); old_pgsize = pgsize; pgsize = force->inumeric(FLERR,arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"one") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); old_oneatom = oneatom; oneatom = force->inumeric(FLERR,arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"binsize") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); binsize_user = force->numeric(FLERR,arg[iarg+1]); if (binsize_user <= 0.0) binsizeflag = 0; else binsizeflag = 1; iarg += 2; } else if (strcmp(arg[iarg],"cluster") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"yes") == 0) cluster_check = 1; else if (strcmp(arg[iarg+1],"no") == 0) cluster_check = 0; else error->all(FLERR,"Illegal neigh_modify command"); iarg += 2; } else if (strcmp(arg[iarg],"include") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); includegroup = group->find(arg[iarg+1]); if (includegroup < 0) error->all(FLERR,"Invalid group ID in neigh_modify command"); if (includegroup && (atom->firstgroupname == NULL || strcmp(arg[iarg+1],atom->firstgroupname) != 0)) error->all(FLERR, "Neigh_modify include group != atom_modify first group"); iarg += 2; } else if (strcmp(arg[iarg],"exclude") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (strcmp(arg[iarg+1],"type") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (nex_type == maxex_type) { maxex_type += EXDELTA; memory->grow(ex1_type,maxex_type,"neigh:ex1_type"); memory->grow(ex2_type,maxex_type,"neigh:ex2_type"); } ex1_type[nex_type] = force->inumeric(FLERR,arg[iarg+2]); ex2_type[nex_type] = force->inumeric(FLERR,arg[iarg+3]); nex_type++; iarg += 4; } else if (strcmp(arg[iarg+1],"group") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (nex_group == maxex_group) { maxex_group += EXDELTA; memory->grow(ex1_group,maxex_group,"neigh:ex1_group"); memory->grow(ex2_group,maxex_group,"neigh:ex2_group"); } ex1_group[nex_group] = group->find(arg[iarg+2]); ex2_group[nex_group] = group->find(arg[iarg+3]); if (ex1_group[nex_group] == -1 || ex2_group[nex_group] == -1) error->all(FLERR,"Invalid group ID in neigh_modify command"); nex_group++; iarg += 4; } else if (strcmp(arg[iarg+1],"molecule") == 0) { if (iarg+3 > narg) error->all(FLERR,"Illegal neigh_modify command"); if (atom->molecule_flag == 0) error->all(FLERR,"Neigh_modify exclude molecule " "requires atom attribute molecule"); if (nex_mol == maxex_mol) { maxex_mol += EXDELTA; memory->grow(ex_mol_group,maxex_mol,"neigh:ex_mol_group"); } ex_mol_group[nex_mol] = group->find(arg[iarg+2]); if (ex_mol_group[nex_mol] == -1) error->all(FLERR,"Invalid group ID in neigh_modify command"); nex_mol++; iarg += 3; } else if (strcmp(arg[iarg+1],"none") == 0) { nex_type = nex_group = nex_mol = 0; iarg += 2; } else error->all(FLERR,"Illegal neigh_modify command"); } else error->all(FLERR,"Illegal neigh_modify command"); } } /* ---------------------------------------------------------------------- remove the first group-group exclusion matching group1, group2 ------------------------------------------------------------------------- */ void Neighbor::exclusion_group_group_delete(int group1, int group2) { int m, mlast; for (m = 0; m < nex_group; m++) if (ex1_group[m] == group1 && ex2_group[m] == group2 ) break; mlast = m; if (mlast == nex_group) error->all(FLERR,"Unable to find group-group exclusion"); for (m = mlast+1; m < nex_group; m++) { ex1_group[m-1] = ex1_group[m]; ex2_group[m-1] = ex2_group[m]; ex1_bit[m-1] = ex1_bit[m]; ex2_bit[m-1] = ex2_bit[m]; } nex_group--; } /* ---------------------------------------------------------------------- return the value of exclude - used to check compatibility with GPU ------------------------------------------------------------------------- */ int Neighbor::exclude_setting() { return exclude; } /* ---------------------------------------------------------------------- return # of bytes of allocated memory ------------------------------------------------------------------------- */ bigint Neighbor::memory_usage() { bigint bytes = 0; bytes += memory->usage(xhold,maxhold,3); for (int i = 0; i < nlist; i++) if (lists[i]) bytes += lists[i]->memory_usage(); for (int i = 0; i < nstencil; i++) bytes += neigh_stencil[i]->memory_usage(); for (int i = 0; i < nbin; i++) bytes += neigh_bin[i]->memory_usage(); if (neigh_bond) bytes += neigh_bond->memory_usage(); if (neigh_angle) bytes += neigh_angle->memory_usage(); if (neigh_dihedral) bytes += neigh_dihedral->memory_usage(); if (neigh_improper) bytes += neigh_improper->memory_usage(); return bytes; } diff --git a/src/neighbor.h b/src/neighbor.h index eb603ad84..d087af9ed 100644 --- a/src/neighbor.h +++ b/src/neighbor.h @@ -1,363 +1,364 @@ /* -*- 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. ------------------------------------------------------------------------- */ #ifndef LMP_NEIGHBOR_H #define LMP_NEIGHBOR_H #include "pointers.h" #include namespace LAMMPS_NS { class Neighbor : protected Pointers { public: int style; // 0,1,2 = nsq, bin, multi int every; // build every this many steps int delay; // delay build for this many steps int dist_check; // 0 = always build, 1 = only if 1/2 dist int ago; // how many steps ago neighboring occurred int pgsize; // size of neighbor page int oneatom; // max # of neighbors for one atom int includegroup; // only build pairwise lists for this group int build_once; // 1 if only build lists once per run double skin; // skin distance double cutneighmin; // min neighbor cutoff for all type pairs double cutneighmax; // max neighbor cutoff for all type pairs double cutneighmaxsq; // cutneighmax squared double **cutneighsq; // neighbor cutneigh sq for each type pair double **cutneighghostsq; // cutneigh sq for each ghost type pair double *cuttype; // for each type, max neigh cut w/ others double *cuttypesq; // cuttype squared double cut_inner_sq; // outer cutoff for inner neighbor list double cut_middle_sq; // outer cutoff for middle neighbor list double cut_middle_inside_sq; // inner cutoff for middle neighbor list int binsizeflag; // user-chosen bin size double binsize_user; // set externally by some accelerator pkgs bigint ncalls; // # of times build has been called bigint ndanger; // # of dangerous builds bigint lastcall; // timestep of last neighbor::build() call // geometry and static info, used by other Neigh classes double *bboxlo,*bboxhi; // ptrs to full domain bounding box // different for orthog vs triclinic double *zeroes; // vector of zeroes for shear history init // exclusion info, used by NeighPair int exclude; // 0 if no type/group exclusions, 1 if yes int nex_type; // # of entries in type exclusion list int *ex1_type,*ex2_type; // pairs of types to exclude int **ex_type; // 2d array of excluded type pairs int nex_group; // # of entries in group exclusion list int *ex1_group,*ex2_group; // pairs of group #'s to exclude int *ex1_bit,*ex2_bit; // pairs of group bits to exclude int nex_mol; // # of entries in molecule exclusion list int *ex_mol_group; // molecule group #'s to exclude int *ex_mol_bit; // molecule group bits to exclude // special info, used by NeighPair int special_flag[4]; // flags for 1-2, 1-3, 1-4 neighbors // cluster setting, used by NeighTopo int cluster_check; // 1 if check bond/angle/etc satisfies minimg // pairwise neighbor lists and corresponding requests int nlist; // # of pairwise neighbor lists int nrequest; // # of requests, same as nlist int old_nrequest; // RQ count for run that just finished class NeighList **lists; class NeighRequest **requests; // from Pair,Fix,Compute,Command classes class NeighRequest **old_requests; // accessed by Finish // data from topology neighbor lists int nbondlist; // list of bonds to compute int **bondlist; int nanglelist; // list of angles to compute int **anglelist; int ndihedrallist; // list of dihedrals to compute int **dihedrallist; int nimproperlist; // list of impropers to compute int **improperlist; // public methods Neighbor(class LAMMPS *); virtual ~Neighbor(); virtual void init(); int request(void *, int instance=0); int decide(); // decide whether to build or not virtual int check_distance(); // check max distance moved since last build void setup_bins(); // setup bins based on box and cutoff virtual void build(int topoflag=1); // build all perpetual neighbor lists virtual void build_topology(); // pairwise topology neighbor lists void build_one(class NeighList *list, int preflag=0); // create a one-time pairwise neigh list void set(int, char **); // set neighbor style and skin distance void reset_timestep(bigint); // reset of timestep counter void modify_params(int, char**); // modify params that control builds void exclusion_group_group_delete(int, int); // rm a group-group exclusion int exclude_setting(); // return exclude value to accelerator pkg bigint memory_usage(); protected: int me,nprocs; int firsttime; // flag for calling init_styles() only once int dimension; // 2/3 for 2d/3d int triclinic; // 0 if domain is orthog, 1 if triclinic int newton_pair; // 0 if newton off for pairwise, 1 if on int must_check; // 1 if must check other classes to reneigh int restart_check; // 1 if restart enabled, 0 if no int fix_check; // # of fixes that induce reneigh int *fixchecklist; // which fixes to check bigint last_setup_bins; // step of last neighbor::setup_bins() call double triggersq; // trigger = build when atom moves this dist double **xhold; // atom coords at last neighbor build int maxhold; // size of xhold array int boxcheck; // 1 if need to store box size double boxlo_hold[3],boxhi_hold[3]; // box size at last neighbor build double corners_hold[8][3]; // box corners at last neighbor build double (*corners)[3]; // ptr to 8 corners of triclinic box double inner[2],middle[2]; // rRESPA cutoffs for extra lists int same; // 1 if NeighRequests are same as last run int old_style,old_triclinic; // previous run info int old_pgsize,old_oneatom; // used to avoid re-creating neigh lists int nstencil_perpetual; // # of perpetual NeighStencil classes int npair_perpetual; // # of perpetual NeighPair classes int *slist; // indices of them in neigh_stencil int *plist; // indices of them in neigh_pair int maxex_type; // max # in exclusion type list int maxex_group; // max # in exclusion group list int maxex_mol; // max # in exclusion molecule list int maxatom; // size of atom-based NeighList arrays int maxrequest; // size of NeighRequest list int maxwt; // max weighting factor applied + 1 // info for other Neigh classes: NBin,NStencil,NPair,NTopo int nbin,nstencil; int nbclass,nsclass,npclass; int bondwhich,anglewhich,dihedralwhich,improperwhich; typedef class NBin *(*BinCreator)(class LAMMPS *); BinCreator *binclass; char **binnames; int *binmasks; class NBin **neigh_bin; typedef class NStencil *(*StencilCreator)(class LAMMPS *); StencilCreator *stencilclass; char **stencilnames; int *stencilmasks; class NStencil **neigh_stencil; typedef class NPair *(*PairCreator)(class LAMMPS *); PairCreator *pairclass; char **pairnames; int *pairmasks; class NPair **neigh_pair; class NTopo *neigh_bond; class NTopo *neigh_angle; class NTopo *neigh_dihedral; class NTopo *neigh_improper; // internal methods // including creator methods for Nbin,Nstencil,Npair instances void init_styles(); void init_pair(); virtual void init_topology(); void print_pairwise_info(); void requests_new2old(); int choose_bin(class NeighRequest *); int choose_stencil(class NeighRequest *); int choose_pair(class NeighRequest *); template static NBin *bin_creator(class LAMMPS *); template static NStencil *stencil_creator(class LAMMPS *); template static NPair *pair_creator(class LAMMPS *); // dummy functions provided by NeighborKokkos, called in init() // otherwise NeighborKokkos would have to overwrite init() int copymode; virtual void init_cutneighsq_kokkos(int) {} virtual void create_kokkos_list(int) {} virtual void init_ex_type_kokkos(int) {} virtual void init_ex_bit_kokkos() {} virtual void init_ex_mol_bit_kokkos() {} }; namespace NeighConst { static const int NB_SSA = 1<<0; static const int NB_INTEL = 1<<1; static const int NB_KOKKOS_DEVICE = 1<<2; static const int NB_KOKKOS_HOST = 1<<3; static const int NS_HALF = 1<<0; static const int NS_FULL = 1<<1; static const int NS_GHOST = 1<<2; static const int NS_SSA = 1<<3; static const int NS_BIN = 1<<4; static const int NS_MULTI = 1<<5; static const int NS_2D = 1<<6; static const int NS_3D = 1<<7; static const int NS_NEWTON = 1<<8; static const int NS_NEWTOFF = 1<<9; static const int NS_ORTHO = 1<<10; static const int NS_TRI = 1<<11; static const int NP_COPY = 1<<0; static const int NP_SKIP = 1<<1; static const int NP_HALF = 1<<2; static const int NP_FULL = 1<<3; static const int NP_HALFFULL = 1<<4; static const int NP_SIZE = 1<<5; static const int NP_RESPA = 1<<6; static const int NP_GHOST = 1<<7; static const int NP_OFF2ON = 1<<8; static const int NP_ONESIDE = 1<<9; static const int NP_SSA = 1<<10; static const int NP_OMP = 1<<11; static const int NP_INTEL = 1<<12; static const int NP_NSQ = 1<<13; static const int NP_BIN = 1<<14; static const int NP_MULTI = 1<<15; static const int NP_NEWTON = 1<<16; static const int NP_NEWTOFF = 1<<17; static const int NP_ORTHO = 1<<18; static const int NP_TRI = 1<<19; static const int NP_KOKKOS_DEVICE = 1<<20; static const int NP_KOKKOS_HOST = 1<<21; + static const int NP_BOND = 1<<22; } } #endif /* ERROR/WARNING messages: E: Neighbor delay must be 0 or multiple of every setting The delay and every parameters set via the neigh_modify command are inconsistent. If the delay setting is non-zero, then it must be a multiple of the every setting. E: Neighbor page size must be >= 10x the one atom setting This is required to prevent wasting too much memory. E: Invalid atom type in neighbor exclusion list Atom types must range from 1 to Ntypes inclusive. W: Neighbor exclusions used with KSpace solver may give inconsistent Coulombic energies This is because excluding specific pair interactions also excludes them from long-range interactions which may not be the desired effect. The special_bonds command handles this consistently by insuring excluded (or weighted) 1-2, 1-3, 1-4 interactions are treated consistently by both the short-range pair style and the long-range solver. This is not done for exclusions of charged atom pairs via the neigh_modify exclude command. E: Neighbor include group not allowed with ghost neighbors This is a current restriction within LAMMPS. E: Neighbor multi not yet enabled for ghost neighbors This is a current restriction within LAMMPS. E: Neighbor multi not yet enabled for granular Self-explanatory. E: Neighbor multi not yet enabled for rRESPA Self-explanatory. E: Too many local+ghost atoms for neighbor list The number of nlocal + nghost atoms on a processor is limited by the size of a 32-bit integer with 2 bits removed for masking 1-2, 1-3, 1-4 neighbors. E: Trying to build an occasional neighbor list before initialization completed This is not allowed. Source code caller needs to be modified. E: Domain too large for neighbor bins The domain has become extremely large so that neighbor bins cannot be used. Most likely, one or more atoms have been blown out of the simulation box to a great distance. E: Cannot use neighbor bins - box size << cutoff Too many neighbor bins will be created. This typically happens when the simulation box is very small in some dimension, compared to the neighbor cutoff. Use the "nsq" style instead of "bin" style. E: Too many neighbor bins This is likely due to an immense simulation box that has blown up to a large size. 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: Invalid group ID in neigh_modify command A group ID used in the neigh_modify command does not exist. E: Neigh_modify include group != atom_modify first group Self-explanatory. E: Neigh_modify exclude molecule requires atom attribute molecule Self-explanatory. */ diff --git a/src/version.h b/src/version.h index 1b3ba22b4..6847e5ff8 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define LAMMPS_VERSION "20 Jan 2017" +#define LAMMPS_VERSION "26 Jan 2017"