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)
17
This pair style srp command calculates a segmental repulsive force
18
between bonds. This is useful for preventing the crossing of bonds if
19
soft non-bonded potentials are used, such as DPD polymer chains.
21
See the doc page for pair_style srp command for usage instructions.
23
There is an example script for this package in examples/USER/srp.
25
Please contact Timothy Sirk for questions (tim.sirk@us.army.mil).
26
------------------------------------------------------------------------- */
34
#include "neigh_list.h"
46
using namespace LAMMPS_NS;
50
#define ONETWOBIT 0x40000000
52
static const char cite_srp[] =
54
" author = {T. Sirk and Y. Sliozberg and J. Brennan and M. Lisal and J. Andzelm},\n"
55
" title = {An enhanced entangled polymer model for dissipative particle dynamics},\n"
56
" journal = {J.~Chem.~Phys.},\n"
62
/* ----------------------------------------------------------------------
63
set size of pair comms in constructor
64
---------------------------------------------------------------------- */
66
PairSRP::PairSRP(LAMMPS *lmp) : Pair(lmp)
70
if (lmp->citeme) lmp->citeme->add(cite_srp);
76
/* ----------------------------------------------------------------------
78
------------------------------------------------------------------------- */
80
void PairSRP::allocate()
83
// particles of bptype inserted by fix srp
84
// bptype is the highest numbered atom type
86
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
87
memory->create(cut, n + 1, n + 1, "pair:cut");
88
memory->create(a0, n + 1, n + 1, "pair:a0");
90
// setflag for atom types
91
memory->create(setflag,n+1,n+1,"pair:setflag");
92
for (int i = 1; i <= n; i++)
93
for (int j = i; j <= n; j++)
99
/* ----------------------------------------------------------------------
101
------------------------------------------------------------------------- */
107
memory->destroy(setflag);
108
memory->destroy(cutsq);
109
memory->destroy(cut);
111
memory->destroy(segment);
114
// check nfix in case all fixes have already been deleted
115
if (modify->nfix) modify->delete_fix("mysrp");
118
/* ----------------------------------------------------------------------
119
compute bond-bond repulsions
120
------------------------------------------------------------------------- */
122
void PairSRP::compute(int eflag, int vflag)
125
// setup energy and virial
127
ev_setup(eflag, vflag);
129
evflag = vflag_fdotr = 0;
131
double **x = atom->x;
132
double **f = atom->f;
133
int nlocal = atom->nlocal;
134
int nall = nlocal + atom->nghost;
136
int i,j,ii,jj,inum,jnum;
139
int *ilist,*jlist,*numneigh,**firstneigh;
142
numneigh = list->numneigh;
143
firstneigh = list->firstneigh;
145
double dx,dy,dz,ti,tj;
146
double wd, lever0, lever1, evdwl, fpair;
147
double fxlever0, fylever0, fzlever0, fxlever1, fylever1, fzlever1;
150
// mapping global to local for atoms inside bond particles
151
// exclude 1-2 neighs if requested
152
if (neighbor->ago == 0){
154
if(exclude) onetwoexclude(ilist, inum, jlist, numneigh, firstneigh);
157
// this pair style only used with hybrid
159
// each atom i is type bptype
160
// each neigh j is type bptype
162
// using midpoint distance option
165
for (ii = 0; ii < inum; ii++) {
169
// two atoms inside bond particle
173
for (jj = 0; jj < jnum; jj++) {
175
jlist = firstneigh[i];
178
// enforce 1-2 exclusions
179
if( (sbmask(j) & exclude) )
183
//retrieve atoms from bond particle
187
// midpt dist bond 0 and 1
188
dx = 0.5*(x[i0][0] - x[i1][0] + x[j0][0] - x[j1][0]);
189
dy = 0.5*(x[i0][1] - x[i1][1] + x[j0][1] - x[j1][1]);
190
dz = 0.5*(x[i0][2] - x[i1][2] + x[j0][2] - x[j1][2]);
191
dijsq = dx*dx + dy*dy + dz*dz;
193
if (dijsq < cutsq[bptype][bptype]){
197
continue; // dij can be 0.0 with soft potentials
199
wd = 1.0 - dij / cut[bptype][bptype];
200
fpair = 0.5 * a0[bptype][bptype] * wd / dij; // 0.5 factor for lever rule
202
// force for bond 0, beads 0,1
203
//force between bonds
208
f[i0][0] += fx; //keep force sign for bond 0
216
f[i1][0] -= fx; //flip force sign for bond 1
224
// ************************************************* //
227
evdwl = 0.5 * a0[bptype][bptype] * cut[bptype][bptype] * wd * wd;
231
ev_tally(i0,i1,nlocal,1,0.5*evdwl,0.0,fpair,dx,dy,dz);
232
ev_tally(j0,j1,nlocal,1,0.5*evdwl,0.0,fpair,dx,dy,dz);
235
if (vflag_fdotr) virial_fdotr_compute();
242
// using min distance option
244
for (ii = 0; ii < inum; ii++) {
251
for (jj = 0; jj < jnum; jj++) {
253
jlist = firstneigh[i];
256
// enforce 1-2 exclusions
257
if( (sbmask(j) & exclude) )
265
getMinDist(x, dx, dy, dz, ti, tj, i0, j0, i1, j1);
266
dijsq = dx*dx + dy*dy + dz*dz;
268
if (dijsq < cutsq[bptype][bptype]){
273
continue; // dij can be 0.0 with soft potentials
275
wd = 1.0 - dij / cut[bptype][bptype];
276
fpair = a0[bptype][bptype] * wd / dij;
278
// force for bond 0, beads 0,1
279
lever0 = 0.5 + ti; // assign force according to lever rule
280
lever1 = 0.5 + tj; // assign force according to lever rule
281
//force between bonds
286
//decompose onto atoms
287
fxlever0 = fx * lever0;
288
fylever0 = fy * lever0;
289
fzlever0 = fz * lever0;
290
fxlever1 = fx * lever1;
291
fylever1 = fy * lever1;
292
fzlever1 = fz * lever1;
294
f[i0][0] += fxlever0; //keep force sign for bond 0
295
f[i0][1] += fylever0;
296
f[i0][2] += fzlever0;
298
f[j0][0] += (fx - fxlever0);
299
f[j0][1] += (fy - fylever0);
300
f[j0][2] += (fz - fzlever0);
302
f[i1][0] -= fxlever1; //flip force sign for bond 1
303
f[i1][1] -= fylever1;
304
f[i1][2] -= fzlever1;
306
f[j1][0] -= (fx - fxlever1);
307
f[j1][1] -= (fy - fylever1);
308
f[j1][2] -= (fz - fzlever1);
310
// ************************************************* //
313
evdwl = 0.5 * a0[bptype][bptype] * cut[bptype][bptype] * wd * wd;
317
ev_tally(i0,i1,nlocal,1,0.5*evdwl,0.0,0.5*fpair,dx,dy,dz);
318
ev_tally(j0,j1,nlocal,1,0.5*evdwl,0.0,0.5*fpair,dx,dy,dz);
321
if (vflag_fdotr) virial_fdotr_compute();
329
/* ----------------------------------------------------------------------
331
------------------------------------------------------------------------- */
333
void PairSRP::settings(int narg, char **arg)
335
if (narg < 3 || narg > 5)
336
error->all(FLERR,"Illegal pair_style command");
338
cut_global = force->numeric(FLERR,arg[0]);
339
btype = force->inumeric(FLERR,arg[1]);
340
if (btype > atom->nbondtypes) error->all(FLERR,"Illegal pair_style command");
346
if (strcmp(arg[2],"min") == 0) min = 1;
347
else if (strcmp(arg[2],"mid") == 0) midpoint = 1;
349
error->all(FLERR,"Illegal pair_style command");
352
// default exclude 1-2
353
// scaling for 1-2, etc not supported
356
while (iarg < narg) {
357
if (strcmp(arg[iarg],"exclude") == 0) {
358
if (iarg+2 > narg) error->all(FLERR,"Illegal pair srp command");
359
if (strcmp(arg[iarg+1],"yes") == 0)
361
if (strcmp(arg[iarg+1],"no") == 0){
362
if (min) error->all(FLERR,"Illegal exclude option in pair srp command");
366
} else error->all(FLERR,"Illegal pair srp command");
369
// highest atom type is saved for bond particles
370
bptype = atom->ntypes;
372
// reset cutoffs if explicitly set
375
for (i = 1; i <= bptype; i++)
376
for (j = i+1; j <= bptype; j++)
377
if (setflag[i][j]) cut[i][j] = cut_global;
381
/* ----------------------------------------------------------------------
383
------------------------------------------------------------------------- */
385
void PairSRP::coeff(int narg, char **arg)
387
if (narg < 3 || narg > 4)
388
error->all(FLERR,"PairSRP: Incorrect args for pair coeff");
389
if (!allocated) allocate();
391
// set ij bond-bond cutoffs
392
int ilo, ihi, jlo, jhi;
393
force->bounds(arg[0], bptype, ilo, ihi);
394
force->bounds(arg[1], bptype, jlo, jhi);
396
double a0_one = force->numeric(FLERR,arg[2]);
397
double cut_one = cut_global;
398
if (narg == 4) cut_one = force->numeric(FLERR,arg[3]);
401
for (int i = ilo; i <= ihi; i++)
403
for (int j = MAX(jlo,i); j <= jhi; j++)
407
cutsq[i][j] = cut_one * cut_one;
413
if (count == 0) error->warning(FLERR,"PairSRP: No pair coefficients were set");
416
/* ----------------------------------------------------------------------
417
init specific to this pair style
418
------------------------------------------------------------------------- */
420
void PairSRP::init_style()
422
if (!force->newton_pair)
423
error->all(FLERR,"PairSRP: Pair srp requires newton pair on");
426
// invoke here instead of constructor
427
// to make restart possible
428
char **fixarg = new char*[3];
429
fixarg[0] = (char *) "mysrp";
430
fixarg[1] = (char *) "all";
431
fixarg[2] = (char *) "SRP";
432
modify->add_fix(3,fixarg);
433
f_srp = (FixSRP *) modify->fix[modify->nfix-1];
436
// set bond type in fix srp
437
// bonds of this type will be represented by bond particles
439
// bptype = bond particle type
442
sprintf(c0, "%d", btype);
443
arg0[0] = (char *) "btype";
445
f_srp->modify_params(2, arg0);
447
// bond particles do not contribute to energy or virial
448
// bond particles do not belong to group all
449
// but thermo normalization is by nall
450
// therefore should turn off normalization
452
MPI_Comm_rank(world,&me);
454
arg1[0] = (char *) "norm";
455
arg1[1] = (char *) "no";
456
output->thermo->modify_params(2, arg1);
458
error->message(FLERR,"Thermo normalization turned off by pair srp");
460
neighbor->request(this,instance_me);
463
/* ----------------------------------------------------------------------
464
init for one type pair i,j and corresponding j,i
465
------------------------------------------------------------------------- */
467
double PairSRP::init_one(int i, int j)
470
if (setflag[i][j] == 0) error->all(FLERR,"PairSRP: All pair coeffs are not set");
472
cut[j][i] = cut[i][j];
478
/* ----------------------------------------------------------------------
479
find min distance for bonds i0/j0 and i1/j1
480
------------------------------------------------------------------------- */
481
inline void PairSRP::getMinDist(double** &x, double &dx, double &dy, double &dz, double &ti, double &tj, int &i0, int &j0, int &i1, int &j1)
483
// move these outside the loop
484
double diffx0, diffy0, diffz0, diffx1, diffy1, diffz1, dPx, dPy, dPz, RiRi, RiRj, RjRj;
485
double denom, termx0, termy0, termz0, num0, termx1, termy1, termz1, num1;
487
// compute midpt dist from 1st atom, 1st bond
488
diffx0 = x[j0][0] - x[i0][0]; // x,y,z from bond 0
489
diffy0 = x[j0][1] - x[i0][1];
490
diffz0 = x[j0][2] - x[i0][2];
492
// compute midpt dist from 1st atom, 2nd bond
493
diffx1 = x[j1][0] - x[i1][0];
494
diffy1 = x[j1][1] - x[i1][1];
495
diffz1 = x[j1][2] - x[i1][2];
498
dPx = 0.5*(diffx0-diffx1) + x[i0][0]-x[i1][0];
499
dPy = 0.5*(diffy0-diffy1) + x[i0][1]-x[i1][1];
500
dPz = 0.5*(diffz0-diffz1) + x[i0][2]-x[i1][2];
503
RiRi = diffx0*diffx0 + diffy0*diffy0 + diffz0*diffz0;
504
RiRj = diffx0*diffx1 + diffy0*diffy1 + diffz0*diffz1;
505
RjRj = diffx1*diffx1 + diffy1*diffy1 + diffz1*diffz1;
506
denom = RiRj*RiRj - RiRi*RjRj;
508
// handle case of parallel lines
509
// reduce to midpt distance
510
if (fabs(denom) < SMALL){
511
if(denom < 0) denom = -BIG;
516
termx0 = RiRj*diffx1 - RjRj*diffx0;
517
termy0 = RiRj*diffy1 - RjRj*diffy0;
518
termz0 = RiRj*diffz1 - RjRj*diffz0;
519
num0 = dPx*termx0 + dPy*termy0 + dPz*termz0;
521
if (ti > 0.5) ti = 0.5;
522
if (ti < -0.5) ti = -0.5;
525
termx1 = RiRj*diffx0 - RiRi*diffx1;
526
termy1 = RiRj*diffy0 - RiRi*diffy1;
527
termz1 = RiRj*diffz0 - RiRi*diffz1;
528
num1 = dPx*termx1 + dPy*termy1 + dPz*termz1;
530
if (tj > 0.5) tj = 0.5;
531
if (tj < -0.5) tj = -0.5;
534
dx = dPx - ti*diffx0 + tj*diffx1;
535
dy = dPy - ti*diffy0 + tj*diffy1;
536
dz = dPz - ti*diffz0 + tj*diffz1;
539
/* --------------------------------------------------------
540
map global id of atoms in stored by each bond particle
541
------------------------------------------------------- */
542
inline void PairSRP::remapBonds(int &nall)
545
memory->grow(segment, nall, 2, "pair:segment");
549
// loop over all bond particles
550
// each bond paricle holds two bond atoms
551
// map global ids of bond atoms to local ids
552
// might not be able to map both bond atoms of j, if j is outside neighcut
553
// these are not on neighlist, so are not used
555
srp = f_srp->array_atom;
557
for (int i = 0; i < nall; i++) {
558
if(atom->type[i] == bptype){
561
tmp = atom->map((int)srp[i][0]);
562
segment[i][0] = domain->closest_image(i,tmp);
563
// repeat with other id
564
tmp = atom->map((int)srp[i][1]);
565
segment[i][1] = domain->closest_image(i,tmp);
570
/* --------------------------------------------------------
571
add exclusions for 1-2 neighs, if requested
572
more complex exclusions or scaling probably not needed
573
------------------------------------------------------- */
574
inline void PairSRP::onetwoexclude(int* &ilist, int &inum, int* &jlist, int* &numneigh, int** &firstneigh)
579
// encode neighs with exclusions
580
// only need 1-2 info for normal uses of srp
581
// add 1-3, etc later if ever needed
583
for (ii = 0; ii < inum; ii++) {
587
// two atoms inside bond particle
591
for (jj = 0; jj < jnum; jj++) {
593
jlist = firstneigh[i];
596
//two atoms inside bond particle
600
// check for a 1-2 neigh
601
if(i0 == i1 || i0 == j1 || i1 == j0 || j0 == j1){
609
/* ----------------------------------------------------------------------
610
proc 0 writes to data file
611
------------------------------------------------------------------------- */
613
void PairSRP::write_data(FILE *fp)
615
for (int i = 1; i <= atom->ntypes; i++)
616
fprintf(fp,"%d %g\n",i,a0[i][i]);
619
/* ----------------------------------------------------------------------
620
proc 0 writes all pairs to data file
621
------------------------------------------------------------------------- */
623
void PairSRP::write_data_all(FILE *fp)
625
for (int i = 1; i <= atom->ntypes; i++)
626
for (int j = i; j <= atom->ntypes; j++)
627
fprintf(fp,"%d %d %g %g\n",i,j,a0[i][j],cut[i][j]);
630
/* ----------------------------------------------------------------------
631
proc 0 writes to restart file
632
------------------------------------------------------------------------- */
634
void PairSRP::write_restart(FILE *fp)
636
write_restart_settings(fp);
639
for (i = 1; i <= atom->ntypes; i++)
640
for (j = i; j <= atom->ntypes; j++) {
641
fwrite(&setflag[i][j],sizeof(int),1,fp);
643
fwrite(&a0[i][j],sizeof(double),1,fp);
644
fwrite(&cut[i][j],sizeof(double),1,fp);
649
/* ----------------------------------------------------------------------
650
proc 0 reads from restart file, bcasts
651
------------------------------------------------------------------------- */
653
void PairSRP::read_restart(FILE *fp)
655
read_restart_settings(fp);
660
for (i = 1; i <= atom->ntypes; i++)
661
for (j = i; j <= atom->ntypes; j++) {
662
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
663
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
666
printf(" i %d j %d \n",i,j);
667
fread(&a0[i][j],sizeof(double),1,fp);
668
fread(&cut[i][j],sizeof(double),1,fp);
670
MPI_Bcast(&a0[i][j],1,MPI_DOUBLE,0,world);
671
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
675
/* ----------------------------------------------------------------------
676
proc 0 writes to restart file
677
------------------------------------------------------------------------- */
679
void PairSRP::write_restart_settings(FILE *fp)
681
fwrite(&cut_global,sizeof(double),1,fp);
682
fwrite(&bptype,sizeof(int),1,fp);
683
fwrite(&btype,sizeof(int),1,fp);
684
fwrite(&min,sizeof(int),1,fp);
685
fwrite(&midpoint,sizeof(int),1,fp);
686
fwrite(&exclude,sizeof(int),1,fp);
689
/* ----------------------------------------------------------------------
690
proc 0 reads from restart file, bcasts
691
------------------------------------------------------------------------- */
693
void PairSRP::read_restart_settings(FILE *fp)
696
fread(&cut_global,sizeof(double),1,fp);
697
fread(&bptype,sizeof(int),1,fp);
698
fread(&btype,sizeof(int),1,fp);
699
fread(&min,sizeof(int),1,fp);
700
fread(&midpoint,sizeof(int),1,fp);
701
fread(&exclude,sizeof(int),1,fp);
703
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);