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