1 /* ----------------------------------------------------------------------
2 This is the
3
4 ██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗████████╗███████╗
5 ██║ ██║██╔════╝ ██╔════╝ ██╔════╝ ██║ ██║╚══██╔══╝██╔════╝
6 ██║ ██║██║ ███╗██║ ███╗██║ ███╗███████║ ██║ ███████╗
7 ██║ ██║██║ ██║██║ ██║██║ ██║██╔══██║ ██║ ╚════██║
8 ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ██║ ██║ ███████║
9 ╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝®
10
11 DEM simulation engine, released by
12 DCS Computing Gmbh, Linz, Austria
13 http://www.dcs-computing.com, office@dcs-computing.com
14
15 LIGGGHTS® is part of CFDEM®project:
16 http://www.liggghts.com | http://www.cfdem.com
17
18 Core developer and main author:
19 Christoph Kloss, christoph.kloss@dcs-computing.com
20
21 LIGGGHTS® is open-source, distributed under the terms of the GNU Public
22 License, version 2 or later. It is distributed in the hope that it will
23 be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have
25 received a copy of the GNU General Public License along with LIGGGHTS®.
26 If not, see http://www.gnu.org/licenses . See also top-level README
27 and LICENSE files.
28
29 LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
30 the producer of the LIGGGHTS® software and the CFDEM®coupling software
31 See http://www.cfdem.com/terms-trademark-policy for details.
32
33 -------------------------------------------------------------------------
34 Contributing author and copyright for this file:
35 This file is from LAMMPS
36 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
37 http://lammps.sandia.gov, Sandia National Laboratories
38 Steve Plimpton, sjplimp@sandia.gov
39
40 Copyright (2003) Sandia Corporation. Under the terms of Contract
41 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
42 certain rights in this software. This software is distributed under
43 the GNU General Public License.
44 ------------------------------------------------------------------------- */
45
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include "fix_external.h"
50 #include "atom.h"
51 #include "update.h"
52 #include "memory.h"
53 #include "error.h"
54 #include "force.h"
55
56 using namespace LAMMPS_NS;
57 using namespace FixConst;
58
59 enum{PF_CALLBACK,PF_ARRAY};
60
61 /* ---------------------------------------------------------------------- */
62
FixExternal(LAMMPS * lmp,int narg,char ** arg)63 FixExternal::FixExternal(LAMMPS *lmp, int narg, char **arg) :
64 Fix(lmp, narg, arg)
65 {
66 if (narg < 4) error->all(FLERR,"Illegal fix external command");
67
68 scalar_flag = 1;
69 global_freq = 1;
70 extscalar = 1;
71
72 if (strcmp(arg[3],"pf/callback") == 0) {
73 if (narg != 6) error->all(FLERR,"Illegal fix external command");
74 mode = PF_CALLBACK;
75 ncall = force->inumeric(FLERR,arg[4]);
76 napply = force->inumeric(FLERR,arg[5]);
77 if (ncall <= 0 || napply <= 0)
78 error->all(FLERR,"Illegal fix external command");
79 } else if (strcmp(arg[3],"pf/array") == 0) {
80 if (narg != 5) error->all(FLERR,"Illegal fix external command");
81 mode = PF_ARRAY;
82 napply = force->inumeric(FLERR,arg[4]);
83 if (napply <= 0) error->all(FLERR,"Illegal fix external command");
84 } else error->all(FLERR,"Illegal fix external command");
85
86 callback = NULL;
87
88 // perform initial allocation of atom-based array
89 // register with Atom class
90
91 fexternal = NULL;
92 grow_arrays(atom->nmax);
93 atom->add_callback(0);
94
95 user_energy = 0.0;
96 }
97
98 /* ---------------------------------------------------------------------- */
99
~FixExternal()100 FixExternal::~FixExternal()
101 {
102 // unregister callbacks to this fix from Atom class
103
104 atom->delete_callback(id,0);
105
106 memory->destroy(fexternal);
107 }
108
109 /* ---------------------------------------------------------------------- */
110
setmask()111 int FixExternal::setmask()
112 {
113 int mask = 0;
114 if (mode == PF_CALLBACK || mode == PF_ARRAY) {
115 mask |= POST_FORCE;
116 mask |= THERMO_ENERGY;
117 mask |= MIN_POST_FORCE;
118 }
119 return mask;
120 }
121
122 /* ---------------------------------------------------------------------- */
123
init()124 void FixExternal::init()
125 {
126 if (mode == PF_CALLBACK && callback == NULL)
127 error->all(FLERR,"Fix external callback function not set");
128 }
129
130 /* ---------------------------------------------------------------------- */
131
setup(int vflag)132 void FixExternal::setup(int vflag)
133 {
134 post_force(vflag);
135 }
136
137 /* ---------------------------------------------------------------------- */
138
min_setup(int vflag)139 void FixExternal::min_setup(int vflag)
140 {
141 post_force(vflag);
142 }
143
144 /* ---------------------------------------------------------------------- */
145
post_force(int vflag)146 void FixExternal::post_force(int vflag)
147 {
148 bigint ntimestep = update->ntimestep;
149
150 // invoke the callback in driver program
151 // it will fill fexternal with forces
152
153 if (mode == PF_CALLBACK && ntimestep % ncall == 0)
154 (this->callback)(ptr_caller,update->ntimestep,
155 atom->nlocal,atom->tag,atom->x,fexternal);
156
157 // add forces from fexternal to atoms in group
158
159 if (ntimestep % napply == 0) {
160 double **f = atom->f;
161 int *mask = atom->mask;
162 int nlocal = atom->nlocal;
163
164 for (int i = 0; i < nlocal; i++)
165 if (mask[i] & groupbit) {
166 f[i][0] += fexternal[i][0];
167 f[i][1] += fexternal[i][1];
168 f[i][2] += fexternal[i][2];
169 }
170 }
171 }
172
173 /* ---------------------------------------------------------------------- */
174
min_post_force(int vflag)175 void FixExternal::min_post_force(int vflag)
176 {
177 post_force(vflag);
178 }
179
180 /* ---------------------------------------------------------------------- */
181
set_energy(double eng)182 void FixExternal::set_energy(double eng)
183 {
184 user_energy = eng;
185 }
186
187 /* ----------------------------------------------------------------------
188 potential energy of added force
189 up to user to set it via set_energy()
190 ------------------------------------------------------------------------- */
191
compute_scalar()192 double FixExternal::compute_scalar()
193 {
194 return user_energy;
195 }
196
197 /* ----------------------------------------------------------------------
198 memory usage of local atom-based array
199 ------------------------------------------------------------------------- */
200
memory_usage()201 double FixExternal::memory_usage()
202 {
203 double bytes = 3*atom->nmax * sizeof(double);
204 return bytes;
205 }
206
207 /* ----------------------------------------------------------------------
208 allocate atom-based array
209 ------------------------------------------------------------------------- */
210
grow_arrays(int nmax)211 void FixExternal::grow_arrays(int nmax)
212 {
213 memory->grow(fexternal,nmax,3,"external:fexternal");
214 }
215
216 /* ----------------------------------------------------------------------
217 copy values within local atom-based array
218 ------------------------------------------------------------------------- */
219
copy_arrays(int i,int j,int delflag)220 void FixExternal::copy_arrays(int i, int j, int delflag)
221 {
222 fexternal[j][0] = fexternal[i][0];
223 fexternal[j][1] = fexternal[i][1];
224 fexternal[j][2] = fexternal[i][2];
225 }
226
227 /* ----------------------------------------------------------------------
228 pack values in local atom-based array for exchange with another proc
229 ------------------------------------------------------------------------- */
230
pack_exchange(int i,double * buf)231 int FixExternal::pack_exchange(int i, double *buf)
232 {
233 buf[0] = fexternal[i][0];
234 buf[1] = fexternal[i][1];
235 buf[2] = fexternal[i][2];
236 return 3;
237 }
238
239 /* ----------------------------------------------------------------------
240 unpack values in local atom-based array from exchange with another proc
241 ------------------------------------------------------------------------- */
242
unpack_exchange(int nlocal,double * buf)243 int FixExternal::unpack_exchange(int nlocal, double *buf)
244 {
245 fexternal[nlocal][0] = buf[0];
246 fexternal[nlocal][1] = buf[1];
247 fexternal[nlocal][2] = buf[2];
248 return 3;
249 }
250
251 /* ----------------------------------------------------------------------
252 external caller sets a callback function to invoke in post_force()
253 ------------------------------------------------------------------------- */
254
set_callback(FnPtr caller_callback,void * caller_ptr)255 void FixExternal::set_callback(FnPtr caller_callback, void *caller_ptr)
256 {
257 callback = caller_callback;
258 ptr_caller = caller_ptr;
259 }
260