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 "compute.h"
16 
17 #include "atom_masks.h"
18 #include "domain.h"
19 #include "error.h"
20 #include "fix.h"
21 #include "group.h"
22 #include "memory.h"
23 #include "modify.h"
24 
25 #include <cstring>
26 
27 using namespace LAMMPS_NS;
28 
29 #define DELTA 4
30 #define BIG MAXTAGINT
31 
32 // allocate space for static class instance variable and initialize it
33 
34 int Compute::instance_total = 0;
35 
36 /* ---------------------------------------------------------------------- */
37 
Compute(LAMMPS * lmp,int narg,char ** arg)38 Compute::Compute(LAMMPS *lmp, int narg, char **arg) :
39   Pointers(lmp),
40   id(nullptr), style(nullptr),
41   vector(nullptr), array(nullptr), vector_atom(nullptr),
42   array_atom(nullptr), vector_local(nullptr), array_local(nullptr), extlist(nullptr),
43   tlist(nullptr), vbiasall(nullptr)
44 {
45   instance_me = instance_total++;
46 
47   if (narg < 3) error->all(FLERR,"Illegal compute command");
48 
49   // compute ID, group, and style
50   // ID must be all alphanumeric chars or underscores
51 
52   id = utils::strdup(arg[0]);
53   if (!utils::is_id(id))
54     error->all(FLERR,"Compute ID must be alphanumeric or underscore characters");
55 
56   igroup = group->find(arg[1]);
57   if (igroup == -1) error->all(FLERR,"Could not find compute group ID");
58   groupbit = group->bitmask[igroup];
59 
60   style = utils::strdup(arg[2]);
61 
62   // set child class defaults
63 
64   scalar_flag = vector_flag = array_flag = 0;
65   peratom_flag = local_flag = 0;
66   size_vector_variable = size_array_rows_variable = 0;
67 
68   tempflag = pressflag = peflag = 0;
69   pressatomflag = peatomflag = 0;
70   create_attribute = 0;
71   tempbias = 0;
72 
73   timeflag = 0;
74   comm_forward = comm_reverse = 0;
75   dynamic = 0;
76   dynamic_group_allow = 1;
77 
78   invoked_scalar = invoked_vector = invoked_array = -1;
79   invoked_peratom = invoked_local = -1;
80   invoked_flag = INVOKED_NONE;
81 
82   // set modify defaults
83 
84   extra_dof = domain->dimension;
85   dynamic_user = 0;
86   fix_dof = 0;
87 
88   // setup list of timesteps
89 
90   ntime = maxtime = 0;
91 
92   // data masks
93 
94   execution_space = Host;
95   datamask_read = ALL_MASK;
96   datamask_modify = ALL_MASK;
97 
98   copymode = 0;
99   kokkosable = 0;
100 }
101 
102 /* ---------------------------------------------------------------------- */
103 
~Compute()104 Compute::~Compute()
105 {
106   if (copymode) return;
107 
108   delete [] id;
109   delete [] style;
110   memory->destroy(tlist);
111 }
112 
113 /* ---------------------------------------------------------------------- */
114 
modify_params(int narg,char ** arg)115 void Compute::modify_params(int narg, char **arg)
116 {
117   if (narg == 0) error->all(FLERR,"Illegal compute_modify command");
118 
119   int iarg = 0;
120   while (iarg < narg) {
121     // added more specific keywords in Mar17
122     // at some point, remove generic extra and dynamic
123     if (strcmp(arg[iarg],"extra") == 0 ||
124         strcmp(arg[iarg],"extra/dof") == 0) {
125       if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command");
126       extra_dof = utils::numeric(FLERR,arg[iarg+1],false,lmp);
127       iarg += 2;
128     } else if (strcmp(arg[iarg],"dynamic") == 0 ||
129                strcmp(arg[iarg],"dynamic/dof") == 0) {
130       if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command");
131       if (strcmp(arg[iarg+1],"no") == 0) dynamic_user = 0;
132       else if (strcmp(arg[iarg+1],"yes") == 0) dynamic_user = 1;
133       else error->all(FLERR,"Illegal compute_modify command");
134       iarg += 2;
135     } else error->all(FLERR,"Illegal compute_modify command");
136   }
137 }
138 
139 /* ----------------------------------------------------------------------
140    calculate adjustment in DOF due to fixes
141 ------------------------------------------------------------------------- */
142 
adjust_dof_fix()143 void Compute::adjust_dof_fix()
144 {
145   Fix **fix = modify->fix;
146   int nfix = modify->nfix;
147 
148   fix_dof = 0;
149   for (int i = 0; i < nfix; i++)
150     if (fix[i]->dof_flag)
151       fix_dof += fix[i]->dof(igroup);
152 }
153 
154 /* ----------------------------------------------------------------------
155    reset extra_dof to its default value
156 ------------------------------------------------------------------------- */
157 
reset_extra_dof()158 void Compute::reset_extra_dof()
159 {
160   extra_dof = domain->dimension;
161 }
162 
163 /* ---------------------------------------------------------------------- */
164 
reset_extra_compute_fix(const char *)165 void Compute::reset_extra_compute_fix(const char *)
166 {
167   error->all(FLERR,
168              "Compute does not allow an extra compute or fix to be reset");
169 }
170 
171 /* ----------------------------------------------------------------------
172    add ntimestep to list of timesteps the compute will be called on
173    do not add if already in list
174    search from top downward, since list of times is in decreasing order
175 ------------------------------------------------------------------------- */
176 
addstep(bigint ntimestep)177 void Compute::addstep(bigint ntimestep)
178 {
179   // i = location in list to insert ntimestep
180 
181   int i;
182   for (i = ntime-1; i >= 0; i--) {
183     if (ntimestep == tlist[i]) return;
184     if (ntimestep < tlist[i]) break;
185   }
186   i++;
187 
188   // extend list as needed
189 
190   if (ntime == maxtime) {
191     maxtime += DELTA;
192     memory->grow(tlist,maxtime,"compute:tlist");
193   }
194 
195   // move remainder of list upward and insert ntimestep
196 
197   for (int j = ntime-1; j >= i; j--) tlist[j+1] = tlist[j];
198   tlist[i] = ntimestep;
199   ntime++;
200 }
201 
202 /* ----------------------------------------------------------------------
203    return 1/0 if ntimestep is or is not in list of calling timesteps
204    if value(s) on top of list are less than ntimestep, delete them
205    search from top downward, since list of times is in decreasing order
206 ------------------------------------------------------------------------- */
207 
matchstep(bigint ntimestep)208 int Compute::matchstep(bigint ntimestep)
209 {
210   for (int i = ntime-1; i >= 0; i--) {
211     if (ntimestep < tlist[i]) return 0;
212     if (ntimestep == tlist[i]) return 1;
213     if (ntimestep > tlist[i]) ntime--;
214   }
215   return 0;
216 }
217 
218 /* ----------------------------------------------------------------------
219    clean out list of timesteps to call the compute on
220 ------------------------------------------------------------------------- */
221 
clearstep()222 void Compute::clearstep()
223 {
224   ntime = 0;
225 }
226