1 // clang-format off
2 /* ----------------------------------------------------------------------
3 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
4 https://www.lammps.org/, Sandia National Laboratories
5 Steve Plimpton, sjplimp@sandia.gov
6
7 Copyright (2003) Sandia Corporation. Under the terms of Contract
8 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9 certain rights in this software. This software is distributed under
10 the GNU General Public License.
11
12 See the README file in the top-level LAMMPS directory.
13 ------------------------------------------------------------------------- */
14
15 #include "ntopo_improper_template.h"
16
17 #include "atom.h"
18 #include "atom_vec.h"
19 #include "force.h"
20 #include "domain.h"
21 #include "update.h"
22 #include "output.h"
23 #include "thermo.h"
24 #include "molecule.h"
25 #include "memory.h"
26 #include "error.h"
27
28
29 using namespace LAMMPS_NS;
30
31 #define DELTA 10000
32
33 /* ---------------------------------------------------------------------- */
34
NTopoImproperTemplate(LAMMPS * lmp)35 NTopoImproperTemplate::NTopoImproperTemplate(LAMMPS *lmp) :
36 NTopo(lmp)
37 {
38 allocate_improper();
39 }
40
41 /* ---------------------------------------------------------------------- */
42
build()43 void NTopoImproperTemplate::build()
44 {
45 int i,m,atom1,atom2,atom3,atom4;
46 int imol,iatom;
47 tagint tagprev;
48 int *num_improper;
49 tagint **improper_atom1,**improper_atom2,**improper_atom3,**improper_atom4;
50 int **improper_type;
51
52 Molecule **onemols = atom->avec->onemols;
53
54 tagint *tag = atom->tag;
55 int *molindex = atom->molindex;
56 int *molatom = atom->molatom;
57 int nlocal = atom->nlocal;
58 int newton_bond = force->newton_bond;
59
60 int lostbond = output->thermo->lostbond;
61 int nmissing = 0;
62 nimproperlist = 0;
63
64 for (i = 0; i < nlocal; i++) {
65 if (molindex[i] < 0) continue;
66 imol = molindex[i];
67 iatom = molatom[i];
68 tagprev = tag[i] - iatom - 1;
69 num_improper = onemols[imol]->num_improper;
70 improper_atom1 = onemols[imol]->improper_atom1;
71 improper_atom2 = onemols[imol]->improper_atom2;
72 improper_atom3 = onemols[imol]->improper_atom3;
73 improper_atom4 = onemols[imol]->improper_atom4;
74 improper_type = onemols[imol]->improper_type;
75
76 for (m = 0; m < num_improper[iatom]; m++) {
77 atom1 = atom->map(improper_atom1[iatom][m]+tagprev);
78 atom2 = atom->map(improper_atom2[iatom][m]+tagprev);
79 atom3 = atom->map(improper_atom3[iatom][m]+tagprev);
80 atom4 = atom->map(improper_atom4[iatom][m]+tagprev);
81 if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
82 nmissing++;
83 if (lostbond == Thermo::ERROR)
84 error->one(FLERR,"Improper atoms {} {} {} {}"
85 " missing on proc {} at step {}",
86 improper_atom1[iatom][m]+tagprev,
87 improper_atom2[iatom][m]+tagprev,
88 improper_atom3[iatom][m]+tagprev,
89 improper_atom4[iatom][m]+tagprev,
90 me,update->ntimestep);
91 continue;
92 }
93 atom1 = domain->closest_image(i,atom1);
94 atom2 = domain->closest_image(i,atom2);
95 atom3 = domain->closest_image(i,atom3);
96 atom4 = domain->closest_image(i,atom4);
97 if (newton_bond ||
98 (i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)) {
99 if (nimproperlist == maximproper) {
100 maximproper += DELTA;
101 memory->grow(improperlist,maximproper,5,"neigh_topo:improperlist");
102 }
103 improperlist[nimproperlist][0] = atom1;
104 improperlist[nimproperlist][1] = atom2;
105 improperlist[nimproperlist][2] = atom3;
106 improperlist[nimproperlist][3] = atom4;
107 improperlist[nimproperlist][4] = improper_type[iatom][m];
108 nimproperlist++;
109 }
110 }
111 }
112
113 if (cluster_check) dihedral_check(nimproperlist,improperlist);
114 if (lostbond == Thermo::IGNORE) return;
115
116 int all;
117 MPI_Allreduce(&nmissing,&all,1,MPI_INT,MPI_SUM,world);
118 if (all && (me == 0))
119 error->warning(FLERR,"Improper atoms missing at step {}",update->ntimestep);
120 }
121