1
/* ----------------------------------------------------------------------
2
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
3
http://lammps.sandia.gov, Sandia National Laboratories
4
Steve Plimpton, sjplimp@sandia.gov
6
Copyright (2003) Sandia Corporation. Under the terms of Contract
7
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
8
certain rights in this software. This software is distributed under
9
the GNU General Public License.
11
See the README file in the top-level LAMMPS directory.
12
------------------------------------------------------------------------- */
14
/* ----------------------------------------------------------------------
15
Contributing authors: Timothy Sirk (ARL), Pieter in't Veld (BASF)
16
------------------------------------------------------------------------- */
31
using namespace LAMMPS_NS;
32
using namespace FixConst;
34
/* ---------------------------------------------------------------------- */
36
FixSRP::FixSRP(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
50
// per-atom array width 2
52
size_peratom_cols = 2;
54
// initial allocation of atom-based array
55
// register with Atom class
57
grow_arrays(atom->nmax);
59
// extends pack_exchange()
60
atom->add_callback(0);
61
atom->add_callback(1); // restart
62
atom->add_callback(2);
65
for (int i = 0; i < atom->nmax; i++)
66
for (int m = 0; m < 3; m++)
69
// assume setup of fix is needed to insert particles
70
// is true if reading from datafile
71
// since a datafile cannot contain bond particles
72
// might be true if reading from restart
73
// a restart file written during the run has bond particles as per atom data
74
// a restart file written after the run does not have bond particles
78
/* ---------------------------------------------------------------------- */
82
// unregister callbacks to this fix from Atom class
83
atom->delete_callback(id,0);
84
atom->delete_callback(id,1);
85
atom->delete_callback(id,2);
86
memory->destroy(array);
89
/* ---------------------------------------------------------------------- */
101
/* ---------------------------------------------------------------------- */
105
if (force->pair_match("hybrid",1) == NULL)
106
error->all(FLERR,"Cannot use pair srp without pair_style hybrid");
108
// the highest numbered atom type should be reserved for bond particles (bptype)
109
// set bptype, unless it will be read from restart
110
if(!restart_reset) bptype = atom->ntypes;
112
// check if bptype is already in use
113
for(int i=0; i < atom->nlocal; i++)
114
if(atom->type[i] == bptype){
115
// error if bptype is already in use
116
// unless starting from a rst file
117
// since rst can contain the bond particles as per atom data
119
error->all(FLERR,"Fix SRP requires an extra atom type");
124
// setup neigh exclusions for diff atom types
125
// bond particles do not interact with other types
126
// type bptype only interacts with itself
128
arg1[0] = (char *) "exclude";
129
arg1[1] = (char *) "type";
133
for(int z = 1; z < bptype; z++)
135
sprintf(c0, "%d", z);
137
sprintf(c1, "%d", bptype);
139
neighbor->modify_params(4, arg1);
143
/* ----------------------------------------------------------------------
144
insert bond particles
145
------------------------------------------------------------------------- */
147
void FixSRP::setup_pre_force(int zz)
152
double delx, dely, delz, rmax, rsq, rsqmax;
153
double **x = atom->x;
154
bigint nall = atom->nlocal + atom->nghost;
155
double xold[nall][3];
157
// make a copy of all coordinates and tags
158
// need this because create_atom overwrites ghost atoms
159
for(int i = 0; i < nall; i++){
160
xold[i][0] = x[i][0];
161
xold[i][1] = x[i][1];
162
xold[i][2] = x[i][2];
165
tagint *tag = atom->tag;
168
for(int i = 0; i < nall; i++){
172
int nlocal = atom->nlocal;
173
int **bondlist = neighbor->bondlist;
174
int nbondlist = neighbor->nbondlist;
178
for (int n = 0; n < nbondlist; n++) {
180
// consider only the user defined bond type
181
if(bondlist[n][2] != btype) continue;
186
// position of bond i
187
xone[0] = (xold[i][0] + xold[j][0])*0.5;
188
xone[1] = (xold[i][1] + xold[j][1])*0.5;
189
xone[2] = (xold[i][2] + xold[j][2])*0.5;
191
// record longest bond
192
// this used to set ghost cutoff
193
delx = xold[j][0] - xold[i][0];
194
dely = xold[j][1] - xold[i][1];
195
delz = xold[j][2] - xold[i][2];
196
rsq = delx*delx + dely*dely + delz*delz;
197
if(rsq > rsqold) rsqold = rsq;
199
// make one particle for each bond
201
// if newton bond, always make particle
202
// if j is local, always make particle
203
// if j is ghost, decide from tag
205
if( force->newton_bond || j < nlocal || tagold[i] > tagold[j] ){
207
atom->avec->create_atom(bptype,xone);
208
// pack tag i/j into buffer for comm
209
array[atom->nlocal-1][0] = (double)tagold[i];
210
array[atom->nlocal-1][1] = (double)tagold[j];
215
// new total # of atoms
216
bigint nblocal = atom->nlocal;
217
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
219
// assign tags for new atoms, update map
220
if (atom->tag_enable) atom->tag_extend();
222
if (atom->map_style) {
230
MPI_Allreduce(&nadd,&Nadd,1,MPI_INT,MPI_SUM,world);
232
sprintf(str, "Inserted %d bond particles.", Nadd);
233
error->message(FLERR,str);
236
// check ghost comm distances
237
// warn and change if shorter from estimate
238
// ghost atoms must be present for bonds on edge of neighbor cutoff
239
// extend cutghost slightly more than half of the longest bond
240
MPI_Allreduce(&rsqold,&rsqmax,1,MPI_DOUBLE,MPI_MAX,world);
242
double cutneighmax_srp = neighbor->cutneighmax + 0.51*rmax;
244
// find smallest cutghost
245
double cutghostmin = comm->cutghost[0];
246
if (cutghostmin > comm->cutghost[1])
247
cutghostmin = comm->cutghost[1];
248
if (cutghostmin > comm->cutghost[2])
249
cutghostmin = comm->cutghost[2];
251
// reset cutghost if needed
252
if (cutneighmax_srp > cutghostmin){
254
sprintf(str, "Extending ghost comm cutoff. New %f, old %f.", cutneighmax_srp, cutghostmin);
255
error->message(FLERR,str);
257
// cutghost updated by comm->setup
258
comm->cutghostuser = cutneighmax_srp;
261
// put new particles in the box before exchange
262
// move owned to new procs
264
// build neigh lists again
266
// if triclinic, lambda coords needed for pbc, exchange, borders
267
if (domain->triclinic) domain->x2lamda(atom->nlocal);
270
if (neighbor->style) neighbor->setup_bins();
272
if (atom->sortfreq > 0) atom->sort();
274
// back to box coords
275
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
276
domain->image_check();
277
domain->box_too_small_check();
278
modify->setup_pre_neighbor();
280
neighbor->ncalls = 0;
283
nlocal = atom->nlocal;
284
nall = atom->nlocal + atom->nghost;
286
for(int i = 0; i < nall; i++)
287
for(int n = 0; n < 3; n++)
290
// do not include bond particles in thermo output
291
// remove them from all groups
292
for(int i=0; i< nlocal; i++)
293
if(atom->type[i] == bptype)
297
/* ----------------------------------------------------------------------
298
set position of bond particles
299
------------------------------------------------------------------------- */
301
void FixSRP::pre_exchange()
304
comm->forward_comm();
306
// reassign bond particle coordinates to midpoint of bonds
307
// only need to do this before neigh rebuild
310
int nlocal = atom->nlocal;
312
for(int ii = 0; ii < nlocal; ii++){
313
if(atom->type[ii] != bptype) continue;
315
i = atom->map((int)array[ii][0]);
316
if(i < 0) error->all(FLERR,"Fix SRP failed to map atom");
317
i = domain->closest_image(ii,i);
319
j = atom->map((int)array[ii][1]);
320
if(j < 0) error->all(FLERR,"Fix SRP failed to map atom");
321
j = domain->closest_image(ii,j);
323
// position of bond particle ii
324
atom->x[ii][0] = (x[i][0] + x[j][0])*0.5;
325
atom->x[ii][1] = (x[i][1] + x[j][1])*0.5;
326
atom->x[ii][2] = (x[i][2] + x[j][2])*0.5;
330
/* ----------------------------------------------------------------------
331
memory usage of local atom-based array
332
------------------------------------------------------------------------- */
334
double FixSRP::memory_usage()
336
double bytes = atom->nmax*2 * sizeof(double);
340
/* ----------------------------------------------------------------------
341
allocate atom-based array
342
------------------------------------------------------------------------- */
344
void FixSRP::grow_arrays(int nmax)
346
memory->grow(array,nmax,2,"fix_srp:array");
350
/* ----------------------------------------------------------------------
351
copy values within local atom-based array
352
called when move to new proc
353
------------------------------------------------------------------------- */
355
void FixSRP::copy_arrays(int i, int j, int delflag)
357
for (int m = 0; m < 2; m++)
358
array[j][m] = array[i][m];
361
/* ----------------------------------------------------------------------
362
initialize one atom's array values
363
called when atom is created
364
------------------------------------------------------------------------- */
366
void FixSRP::set_arrays(int i)
372
/* ----------------------------------------------------------------------
373
pack values in local atom-based array for exchange with another proc
374
------------------------------------------------------------------------- */
376
int FixSRP::pack_exchange(int i, double *buf)
378
for (int m = 0; m < 2; m++) buf[m] = array[i][m];
382
/* ----------------------------------------------------------------------
383
unpack values in local atom-based array from exchange with another proc
384
------------------------------------------------------------------------- */
386
int FixSRP::unpack_exchange(int nlocal, double *buf)
388
for (int m = 0; m < 2; m++) array[nlocal][m] = buf[m];
391
/* ----------------------------------------------------------------------
392
pack values for border communication at re-neighboring
393
------------------------------------------------------------------------- */
395
int FixSRP::pack_border(int n, int *list, double *buf)
397
// pack buf for border com
400
for (i = 0; i < n; i++) {
402
buf[m++] = array[j][0];
403
buf[m++] = array[j][1];
408
/* ----------------------------------------------------------------------
409
unpack values for border communication at re-neighboring
410
------------------------------------------------------------------------- */
412
int FixSRP::unpack_border(int n, int first, double *buf)
414
// unpack buf into array
419
for (i = first; i < last; i++){
420
array[i][0] = static_cast<int> (buf[m++]);
421
array[i][1] = static_cast<int> (buf[m++]);
426
/* ----------------------------------------------------------------------
427
remove particles after run
428
------------------------------------------------------------------------- */
430
void FixSRP::post_run()
432
// all bond particles are removed after each run
433
// useful for write_data and write_restart commands
434
// since those commands occur between runs
436
bigint natoms_previous = atom->natoms;
437
int nlocal = atom->nlocal;
439
memory->create(dlist,nlocal,"fix_srp:dlist");
441
for (int i = 0; i < nlocal; i++){
442
if(atom->type[i] == bptype)
448
// delete local atoms flagged in dlist
451
AtomVec *avec = atom->avec;
456
avec->copy(nlocal-1,i,1);
457
dlist[i] = dlist[nlocal-1];
462
atom->nlocal = nlocal;
463
memory->destroy(dlist);
465
// reset atom->natoms
466
// reset atom->map if it exists
467
// set nghost to 0 so old ghosts won't be mapped
469
bigint nblocal = atom->nlocal;
470
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
471
if (atom->map_style) {
477
// print before and after atom count
479
bigint ndelete = natoms_previous - atom->natoms;
482
if (screen) fprintf(screen,"Deleted " BIGINT_FORMAT
483
" atoms, new total = " BIGINT_FORMAT "\n",
484
ndelete,atom->natoms);
485
if (logfile) fprintf(logfile,"Deleted " BIGINT_FORMAT
486
" atoms, new total = " BIGINT_FORMAT "\n",
487
ndelete,atom->natoms);
490
// verlet calls box_too_small_check() in post_run
491
// this check maps all bond partners
492
// therefore need ghosts
494
// need to convert to lambda coords before apply pbc
495
if (domain->triclinic) domain->x2lamda(atom->nlocal);
499
if (atom->sortfreq > 0) atom->sort();
501
// change back to box coordinates
502
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
505
/* ----------------------------------------------------------------------
506
pack values in local atom-based arrays for restart file
507
------------------------------------------------------------------------- */
509
int FixSRP::pack_restart(int i, double *buf)
513
buf[m++] = array[i][0];
514
buf[m++] = array[i][1];
518
/* ----------------------------------------------------------------------
519
unpack values from atom->extra array to restart the fix
520
------------------------------------------------------------------------- */
522
void FixSRP::unpack_restart(int nlocal, int nth)
524
double **extra = atom->extra;
526
// skip to Nth set of extra values
528
for (int i = 0; i < nth; i++){
529
m += static_cast<int> (extra[nlocal][m]);
533
array[nlocal][0] = extra[nlocal][m++];
534
array[nlocal][1] = extra[nlocal][m++];
537
/* ----------------------------------------------------------------------
538
maxsize of any atom's restart data
539
------------------------------------------------------------------------- */
541
int FixSRP::maxsize_restart()
546
/* ----------------------------------------------------------------------
547
size of atom nlocal's restart data
548
------------------------------------------------------------------------- */
550
int FixSRP::size_restart(int nlocal)
555
/* ----------------------------------------------------------------------
556
pack global state of Fix
557
------------------------------------------------------------------------- */
559
void FixSRP::write_restart(FILE *fp)
563
list[n++] = comm->cutghostuser;
568
int size = n * sizeof(double);
569
fwrite(&size,sizeof(int),1,fp);
570
fwrite(list,sizeof(double),n,fp);
574
/* ----------------------------------------------------------------------
575
use info from restart file to restart the Fix
576
------------------------------------------------------------------------- */
578
void FixSRP::restart(char *buf)
581
double *list = (double *) buf;
583
comm->cutghostuser = static_cast<double> (list[n++]);
584
btype = static_cast<int> (list[n++]);
585
bptype = static_cast<int> (list[n++]);
588
/* ----------------------------------------------------------------------
589
interface with pair class
590
pair srp sets the bond type in this fix
591
------------------------------------------------------------------------- */
593
int FixSRP::modify_param(int narg, char **arg)
595
if (strcmp(arg[0],"btype") == 0) {
596
btype = atoi(arg[1]);