Removed several files that should not have been included
This commit is contained in:
@ -1,721 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pair_gran_dmt_rolling.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "fix.h"
|
||||
#include "fix_neigh_history.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "math_const.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define TWOTHIRDS 0.6666666666666666
|
||||
#define EPSILON 1e-10
|
||||
|
||||
enum {TSUJI, BRILLIANTOV};
|
||||
enum {INDEP, BRILLROLL};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairGranDMTRolling::PairGranDMTRolling(LAMMPS *lmp) :
|
||||
PairGranHookeHistory(lmp, 7),
|
||||
E_one(0), G_one(0), pois(0), muS_one(0), cor(0), alpha_one(0),
|
||||
Ecoh_one(0), kR_one(0), muR_one(0), etaR_one(0)
|
||||
{
|
||||
int ntypes = atom->ntypes;
|
||||
memory->create(E,ntypes+1,ntypes+1,"pair:E");
|
||||
memory->create(G,ntypes+1,ntypes+1,"pair:G");
|
||||
memory->create(alpha,ntypes+1,ntypes+1,"pair:alpha");
|
||||
memory->create(gamman,ntypes+1,ntypes+1,"pair:gamman");
|
||||
memory->create(muS,ntypes+1,ntypes+1,"pair:muS");
|
||||
memory->create(Ecoh,ntypes+1,ntypes+1,"pair:Ecoh");
|
||||
memory->create(kR,ntypes+1,ntypes+1,"pair:kR");
|
||||
memory->create(muR,ntypes+1,ntypes+1,"pair:muR");
|
||||
memory->create(etaR,ntypes+1,ntypes+1,"pair:etaR");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
PairGranDMTRolling::~PairGranDMTRolling()
|
||||
{
|
||||
delete [] E_one;
|
||||
delete [] G_one;
|
||||
delete [] pois;
|
||||
delete [] muS_one;
|
||||
delete [] cor;
|
||||
delete [] alpha_one;
|
||||
delete [] Ecoh_one;
|
||||
delete [] kR_one;
|
||||
delete [] muR_one;
|
||||
delete [] etaR_one;
|
||||
//TODO: Make all this work with standard pair coeff type commands.
|
||||
//Also these should not be in the destructor.
|
||||
memory->destroy(E);
|
||||
memory->destroy(G);
|
||||
memory->destroy(alpha);
|
||||
memory->destroy(gamman);
|
||||
memory->destroy(muS);
|
||||
memory->destroy(Ecoh);
|
||||
memory->destroy(kR);
|
||||
memory->destroy(muR);
|
||||
memory->destroy(etaR);
|
||||
}
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranDMTRolling::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,ii,jj,inum,jnum;
|
||||
int itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz,nx,ny,nz;
|
||||
double radi,radj,radsum,rsq,r,rinv,rsqinv,R,a;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
|
||||
double wr1,wr2,wr3;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double kn, kt, k_Q, k_R, eta_N, eta_T, eta_Q, eta_R;
|
||||
double Fhz, Fdamp, Fdmt, Fne, Fntot, Fscrit, Frcrit;
|
||||
double overlap;
|
||||
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
|
||||
double relrot1,relrot2,relrot3,vrl1,vrl2,vrl3,vrlmag,vrlmaginv;
|
||||
double rollmag, rolldotn, scalefac;
|
||||
double fr, fr1, fr2, fr3;
|
||||
double signtwist, magtwist, magtortwist, Mtcrit;
|
||||
double fs,fs1,fs2,fs3,roll1,roll2,roll3,torroll1,torroll2,torroll3;
|
||||
double tortwist1, tortwist2, tortwist3;
|
||||
double shrmag,rsht;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
int *touch,**firsttouch;
|
||||
double *shear,*allshear,**firstshear;
|
||||
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = vflag_fdotr = 0;
|
||||
|
||||
int shearupdate = 1;
|
||||
if (update->setupflag) shearupdate = 0;
|
||||
|
||||
// update rigid body info for owned & ghost atoms if using FixRigid masses
|
||||
// body[i] = which body atom I is in, -1 if none
|
||||
// mass_body = mass of each rigid body
|
||||
|
||||
if (fix_rigid && neighbor->ago == 0){
|
||||
int tmp;
|
||||
int *body = (int *) fix_rigid->extract("body",tmp);
|
||||
double *mass_body = (double *) fix_rigid->extract("masstotal",tmp);
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(mass_rigid);
|
||||
nmax = atom->nmax;
|
||||
memory->create(mass_rigid,nmax,"pair:mass_rigid");
|
||||
}
|
||||
int nlocal = atom->nlocal;
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (body[i] >= 0) mass_rigid[i] = mass_body[body[i]];
|
||||
else mass_rigid[i] = 0.0;
|
||||
comm->forward_comm_pair(this);
|
||||
}
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double **omega = atom->omega;
|
||||
double **torque = atom->torque;
|
||||
double *radius = atom->radius;
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = fix_history->firstflag;
|
||||
firstshear = fix_history->firstvalue;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
touch = firsttouch[i];
|
||||
allshear = firstshear[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
jtype = type[j];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum){
|
||||
// unset non-touching neighbors
|
||||
touch[jj] = 0;
|
||||
shear = &allshear[size_history*jj];
|
||||
for (int k = 0; k < size_history; k++)
|
||||
shear[k] = 0.0;
|
||||
} else {
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
R = radi*radj/(radi+radj);
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz; //v_R . n
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
//****************************************
|
||||
//Normal force = Hertzian contact + DMT + damping
|
||||
//****************************************
|
||||
overlap = radsum - r;
|
||||
a = sqrt(R*overlap);
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
Fhz = kn*overlap;
|
||||
|
||||
//Damping (based on Tsuji et al)
|
||||
if (normaldamp == BRILLIANTOV) eta_N = a*meff*gamman[itype][jtype];
|
||||
else if (normaldamp == TSUJI) eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
//DMT
|
||||
Fdmt = -4*MY_PI*Ecoh[itype][jtype]*R;
|
||||
|
||||
Fne = Fhz + Fdmt;
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
//****************************************
|
||||
//Tangential force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
// tangential component
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
//Luding Gran Matt 2008, v10,p235 suggests correcting radi and radj by subtracting
|
||||
//delta/2, i.e. instead of radi, use distance to center of contact point?
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// relative tangential velocities
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
touch[jj] = 1;
|
||||
shear = &allshear[size_history*jj];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// Rotate and update shear displacements.
|
||||
// See e.g. eq. 17 of Luding, Gran. Matter 2008, v10,p235
|
||||
if (shearupdate) {
|
||||
rsht = shear[0]*nx + shear[1]*ny + shear[2]*nz;
|
||||
if (fabs(rsht) < EPSILON) rsht = 0;
|
||||
if (rsht > 0){
|
||||
scalefac = shrmag/(shrmag - rsht); //if rhst == shrmag, contacting pair has rotated 90 deg. in one step, in which case you deserve a crash!
|
||||
shear[0] -= rsht*nx;
|
||||
shear[1] -= rsht*ny;
|
||||
shear[2] -= rsht*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[0] *= scalefac;
|
||||
shear[1] *= scalefac;
|
||||
shear[2] *= scalefac;
|
||||
}
|
||||
//Update shear history
|
||||
shear[0] += vtr1*dt;
|
||||
shear[1] += vtr2*dt;
|
||||
shear[2] += vtr3*dt;
|
||||
}
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
// following Zhao and Marshall Phys Fluids v20, p043302 (2008)
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N; //Based on discussion in Marshall; eta_T can also be an independent parameter
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1; //eq 26
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Fscrit = muS[itype][jtype] * fabs(Fne);
|
||||
// For JKR, use eq 43 of Marshall. For DMT, use Fne instead
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
//shear[0] = (Fcrit/fs) * (shear[0] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[1] = (Fcrit/fs) * (shear[1] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[2] = (Fcrit/fs) * (shear[2] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
shear[0] = -1.0/kt*(Fscrit*fs1/fs + eta_T*vtr1); //Same as above, but simpler (check!)
|
||||
shear[1] = -1.0/kt*(Fscrit*fs2/fs + eta_T*vtr2);
|
||||
shear[2] = -1.0/kt*(Fscrit*fs3/fs + eta_T*vtr3);
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = 0.0;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Rolling force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
relrot1 = omega[i][0] - omega[j][0];
|
||||
relrot2 = omega[i][1] - omega[j][1];
|
||||
relrot3 = omega[i][2] - omega[j][2];
|
||||
|
||||
// rolling velocity, see eq. 31 of Wang et al, Particuology v 23, p 49 (2015)
|
||||
// This is different from the Marshall papers, which use the Bagi/Kuhn formulation
|
||||
// for rolling velocity (see Wang et al for why the latter is wrong)
|
||||
vrl1 = R*(relrot2*nz - relrot3*ny); //- 0.5*((radj-radi)/radsum)*vtr1;
|
||||
vrl2 = R*(relrot3*nx - relrot1*nz); //- 0.5*((radj-radi)/radsum)*vtr2;
|
||||
vrl3 = R*(relrot1*ny - relrot2*nx); //- 0.5*((radj-radi)/radsum)*vtr3;
|
||||
vrlmag = sqrt(vrl1*vrl1+vrl2*vrl2+vrl3*vrl3);
|
||||
if (vrlmag != 0.0) vrlmaginv = 1.0/vrlmag;
|
||||
else vrlmaginv = 0.0;
|
||||
|
||||
// Rolling displacement
|
||||
rollmag = sqrt(shear[3]*shear[3] + shear[4]*shear[4] + shear[5]*shear[5]);
|
||||
rolldotn = shear[3]*nx + shear[4]*ny + shear[5]*nz;
|
||||
|
||||
if (shearupdate) {
|
||||
if (fabs(rolldotn) < EPSILON) rolldotn = 0;
|
||||
if (rolldotn > 0){ //Rotate into tangential plane
|
||||
scalefac = rollmag/(rollmag - rolldotn);
|
||||
shear[3] -= rolldotn*nx;
|
||||
shear[4] -= rolldotn*ny;
|
||||
shear[5] -= rolldotn*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[3] *= scalefac;
|
||||
shear[4] *= scalefac;
|
||||
shear[5] *= scalefac;
|
||||
}
|
||||
shear[3] += vrl1*dt;
|
||||
shear[4] += vrl2*dt;
|
||||
shear[5] += vrl3*dt;
|
||||
}
|
||||
|
||||
k_R = kR[itype][jtype];
|
||||
if (rollingdamp == INDEP) eta_R = etaR[itype][jtype];
|
||||
else if (rollingdamp == BRILLROLL) eta_R = muR[itype][jtype]*fabs(Fne);
|
||||
fr1 = -k_R*shear[3] - eta_R*vrl1;
|
||||
fr2 = -k_R*shear[4] - eta_R*vrl2;
|
||||
fr3 = -k_R*shear[5] - eta_R*vrl3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Frcrit = muR[itype][jtype] * fabs(Fne);
|
||||
|
||||
rollmag = sqrt(shear[3]*shear[3] + shear[4]*shear[4] + shear[5]*shear[5]);
|
||||
fr = sqrt(fr1*fr1 + fr2*fr2 + fr3*fr3);
|
||||
if (fr > Frcrit) {
|
||||
if (rollmag != 0.0) {
|
||||
shear[3] = -1.0/k_R*(Frcrit*fr1/fr + eta_R*vrl1);
|
||||
shear[4] = -1.0/k_R*(Frcrit*fr2/fr + eta_R*vrl2);
|
||||
shear[5] = -1.0/k_R*(Frcrit*fr3/fr + eta_R*vrl3);
|
||||
fr1 *= Frcrit/fr;
|
||||
fr2 *= Frcrit/fr;
|
||||
fr3 *= Frcrit/fr;
|
||||
} else fr1 = fr2 = fr3 = 0.0;
|
||||
}
|
||||
|
||||
|
||||
//****************************************
|
||||
// Twisting torque, including shear history effects
|
||||
//****************************************
|
||||
magtwist = relrot1*nx + relrot2*ny + relrot3*nz; //Omega_T (eq 29 of Marshall)
|
||||
shear[6] += magtwist*dt;
|
||||
k_Q = 0.5*kt*a*a;; //eq 32
|
||||
eta_Q = 0.5*eta_T*a*a;
|
||||
magtortwist = -k_Q*shear[6] - eta_Q*magtwist;//M_t torque (eq 30)
|
||||
|
||||
signtwist = (magtwist > 0) - (magtwist < 0);
|
||||
Mtcrit=TWOTHIRDS*a*Fscrit;//critical torque (eq 44)
|
||||
if (fabs(magtortwist) > Mtcrit){
|
||||
shear[6] = 1.0/k_Q*(Mtcrit*signtwist - eta_Q*magtwist);
|
||||
magtortwist = -Mtcrit * signtwist; //eq 34
|
||||
}
|
||||
|
||||
// Apply forces & torques
|
||||
|
||||
fx = nx*Fntot + fs1;
|
||||
fy = ny*Fntot + fs2;
|
||||
fz = nz*Fntot + fs3;
|
||||
|
||||
f[i][0] += fx;
|
||||
f[i][1] += fy;
|
||||
f[i][2] += fz;
|
||||
|
||||
tor1 = ny*fs3 - nz*fs2;
|
||||
tor2 = nz*fs1 - nx*fs3;
|
||||
tor3 = nx*fs2 - ny*fs1;
|
||||
|
||||
torque[i][0] -= radi*tor1;
|
||||
torque[i][1] -= radi*tor2;
|
||||
torque[i][2] -= radi*tor3;
|
||||
|
||||
tortwist1 = magtortwist * nx;
|
||||
tortwist2 = magtortwist * ny;
|
||||
tortwist3 = magtortwist * nz;
|
||||
|
||||
torque[i][0] += tortwist1;
|
||||
torque[i][1] += tortwist2;
|
||||
torque[i][2] += tortwist3;
|
||||
|
||||
torroll1 = R*(ny*fr3 - nz*fr2); //n cross fr
|
||||
torroll2 = R*(nz*fr1 - nx*fr3);
|
||||
torroll3 = R*(nx*fr2 - ny*fr1);
|
||||
|
||||
torque[i][0] += torroll1;
|
||||
torque[i][1] += torroll2;
|
||||
torque[i][2] += torroll3;
|
||||
|
||||
if (force->newton_pair || j < nlocal) {
|
||||
f[j][0] -= fx;
|
||||
f[j][1] -= fy;
|
||||
f[j][2] -= fz;
|
||||
|
||||
torque[j][0] -= radj*tor1;
|
||||
torque[j][1] -= radj*tor2;
|
||||
torque[j][2] -= radj*tor3;
|
||||
|
||||
torque[j][0] -= tortwist1;
|
||||
torque[j][1] -= tortwist2;
|
||||
torque[j][2] -= tortwist3;
|
||||
|
||||
torque[j][0] -= torroll1;
|
||||
torque[j][1] -= torroll2;
|
||||
torque[j][2] -= torroll3;
|
||||
}
|
||||
if (evflag) ev_tally_xyz(i,j,nlocal,0,
|
||||
0.0,0.0,fx,fy,fz,delx,dely,delz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranDMTRolling::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 6) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
if (narg < 8*ntypes) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
E_one = new double[ntypes+1];
|
||||
G_one = new double[ntypes+1];
|
||||
pois = new double[ntypes+1];
|
||||
muS_one = new double[ntypes+1];
|
||||
cor = new double[ntypes+1];
|
||||
alpha_one = new double[ntypes+1];
|
||||
Ecoh_one = new double[ntypes+1];
|
||||
kR_one = new double[ntypes+1];
|
||||
muR_one = new double[ntypes+1];
|
||||
etaR_one = new double[ntypes+1];
|
||||
|
||||
for (int i=0; i < ntypes;i++){
|
||||
E_one[i+1] = force->numeric(FLERR, arg[i]);
|
||||
G_one[i+1] = force->numeric(FLERR, arg[ntypes+i]);
|
||||
muS_one[i+1] = force->numeric(FLERR, arg[2*ntypes+i]);
|
||||
cor[i+1] = force->numeric(FLERR, arg[3*ntypes+i]);
|
||||
Ecoh_one[i+1] = force->numeric(FLERR, arg[4*ntypes+i]);
|
||||
kR_one[i+1] = force->numeric(FLERR, arg[5*ntypes+i]);
|
||||
muR_one[i+1] = force->numeric(FLERR, arg[6*ntypes+i]);
|
||||
etaR_one[i+1] = force->numeric(FLERR, arg[7*ntypes+i]);
|
||||
}
|
||||
|
||||
//Defaults
|
||||
normaldamp = TSUJI;
|
||||
rollingdamp = INDEP;
|
||||
|
||||
int iarg = 8*ntypes;
|
||||
while (iarg < narg){
|
||||
if (strcmp(arg[iarg],"normaldamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"tsuji") == 0) normaldamp = TSUJI;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) normaldamp = BRILLIANTOV;
|
||||
else error->all(FLERR, "Invalid normal damping model for pair/gran/dmt/rolling");
|
||||
iarg += 2;
|
||||
}
|
||||
else if (strcmp(arg[iarg],"rollingdamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"independent") == 0) rollingdamp = INDEP;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) rollingdamp = BRILLROLL;
|
||||
else error->all(FLERR, "Invalid rolling damping model for pair/gran/dmt/rolling");
|
||||
iarg += 2;
|
||||
}
|
||||
else{
|
||||
iarg +=1;
|
||||
}
|
||||
}
|
||||
|
||||
//Derived from inputs
|
||||
for (int i=1; i <= ntypes; i++){
|
||||
pois[i] = E_one[i]/(2.0*G_one[i]) - 1.0;
|
||||
alpha_one[i] = 1.2728-4.2783*cor[i]+11.087*cor[i]*cor[i]-22.348*cor[i]*cor[i]*cor[i]+27.467*cor[i]*cor[i]*cor[i]*cor[i]-18.022*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]+4.8218*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]*cor[i];
|
||||
for (int j=i; j <= ntypes; j++){
|
||||
E[i][j] = E[j][i] = 1/((1-pois[i]*pois[i])/E_one[i]+(1-pois[j]*pois[j])/E_one[j]);
|
||||
G[i][j] = G[j][i] = 1/((2-pois[i])/G_one[i]+(2-pois[j])/G_one[j]);
|
||||
if (normaldamp == TSUJI){
|
||||
alpha[i][j] = alpha[j][i] = sqrt(alpha_one[i]*alpha_one[j]);
|
||||
}
|
||||
else if (normaldamp == BRILLIANTOV){
|
||||
gamman[i][j] = gamman[j][i] = sqrt(cor[i]*cor[j]);
|
||||
}
|
||||
muS[i][j] = muS[j][i] = sqrt(muS_one[i]*muS_one[j]);
|
||||
Ecoh[i][j] = Ecoh[j][i] = sqrt(Ecoh_one[i]*Ecoh_one[j]);
|
||||
kR[i][j] = kR[j][i] = sqrt(kR_one[i]*kR_one[j]);
|
||||
etaR[i][j] = etaR[j][i] = sqrt(etaR_one[i]*etaR_one[j]);
|
||||
muR[i][j] = muR[j][i] = sqrt(muR_one[i]*muR_one[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double PairGranDMTRolling::single(int i, int j, int itype, int jtype,
|
||||
double rsq,
|
||||
double factor_coul, double factor_lj,
|
||||
double &fforce)
|
||||
{
|
||||
double radi,radj,radsum;
|
||||
double r,rinv,rsqinv,delx,dely,delz, nx, ny, nz, R;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3,wr1,wr2,wr3;
|
||||
double overlap, a;
|
||||
double mi,mj,meff,damp,kn,kt;
|
||||
double Fhz,Fdamp,Fdmt,Fne,Fntot,Fscrit;
|
||||
double eta_N,eta_T;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double fs1,fs2,fs3,fs;
|
||||
double shrmag;
|
||||
|
||||
|
||||
double *radius = atom->radius;
|
||||
radi = radius[i];
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum) {
|
||||
fforce = 0.0;
|
||||
svector[0] = svector[1] = svector[2] = svector[3] = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
R = radi*radj/radsum;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
double **v = atom->v;
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
double **x = atom->x;
|
||||
delx = x[i][0] - x[j][0];
|
||||
dely = x[i][1] - x[j][1];
|
||||
delz = x[i][2] - x[j][2];
|
||||
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz;
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// tangential component
|
||||
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
|
||||
double **omega = atom->omega;
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
// NOTE: ensure mass_rigid is current for owned+ghost atoms?
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
|
||||
// normal force = Hertzian contact + normal velocity damping
|
||||
overlap = radsum - r;
|
||||
a = sqrt(R*overlap);
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
Fhz = kn*overlap;
|
||||
|
||||
//Damping (based on Tsuji et al)
|
||||
|
||||
eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
//DMT
|
||||
Fdmt = -4*MY_PI*Ecoh[itype][jtype]*R;
|
||||
|
||||
Fne = Fhz + Fdmt;
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
// relative velocities
|
||||
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
// neighprev = index of found neigh on previous call
|
||||
// search entire jnum list of neighbors of I for neighbor J
|
||||
// start from neighprev, since will typically be next neighbor
|
||||
// reset neighprev to 0 as necessary
|
||||
|
||||
int jnum = list->numneigh[i];
|
||||
int *jlist = list->firstneigh[i];
|
||||
double *allshear = fix_history->firstvalue[i];
|
||||
|
||||
for (int jj = 0; jj < jnum; jj++) {
|
||||
neighprev++;
|
||||
if (neighprev >= jnum) neighprev = 0;
|
||||
if (jlist[neighprev] == j) break;
|
||||
}
|
||||
|
||||
double *shear = &allshear[size_history*neighprev];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N;
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1;
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
Fscrit= muS[itype][jtype] * fabs(Fne);
|
||||
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
fs *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = fs = 0.0;
|
||||
}
|
||||
|
||||
// set all forces and return no energy
|
||||
|
||||
fforce = Fntot;
|
||||
|
||||
// set single_extra quantities
|
||||
|
||||
svector[0] = fs1;
|
||||
svector[1] = fs2;
|
||||
svector[2] = fs3;
|
||||
svector[3] = fs;
|
||||
svector[4] = vn1;
|
||||
svector[5] = vn2;
|
||||
svector[6] = vn3;
|
||||
svector[7] = vt1;
|
||||
svector[8] = vt2;
|
||||
svector[9] = vt3;
|
||||
return 0.0;
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(gran/dmt/rolling,PairGranDMTRolling)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_GRAN_DMT_ROLLING_H
|
||||
#define LMP_PAIR_GRAN_DMT_ROLLING_H
|
||||
|
||||
#include "pair_gran_hooke_history.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairGranDMTRolling : public PairGranHookeHistory {
|
||||
public:
|
||||
PairGranDMTRolling(class LAMMPS *);
|
||||
virtual ~PairGranDMTRolling();
|
||||
virtual void compute(int, int);
|
||||
void settings(int, char **); //Eventually set this through coeff method so that user can specify a particular i-j set of coefficients
|
||||
double single(int, int, int, int, double, double, double, double &);
|
||||
double *E_one, *G_one, *pois, *muS_one, *cor, *alpha_one, *Ecoh_one, *kR_one, *muR_one, *etaR_one; //Public so as to be accessible to fix/wall/gran
|
||||
private:
|
||||
double **E, **G, **alpha, **muS, **Ecoh, **kR, **muR, **etaR, **gamman;
|
||||
int normaldamp, rollingdamp;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
@ -1,719 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pair_gran_dmt_rolling.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "fix.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "math_const.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define TWOTHIRDS 0.6666666666666666
|
||||
#define EPSILON 1e-10
|
||||
|
||||
enum {TSUJI, BRILLIANTOV};
|
||||
enum {INDEP, BRILLROLL};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairGranDMTRolling::PairGranDMTRolling(LAMMPS *lmp) :
|
||||
PairGranHookeHistory(lmp, 7),
|
||||
E_one(0), G_one(0), pois(0), muS_one(0), cor(0), alpha_one(0),
|
||||
Ecoh_one(0), kR_one(0), muR_one(0), etaR_one(0)
|
||||
{
|
||||
int ntypes = atom->ntypes;
|
||||
memory->create(E,ntypes+1,ntypes+1,"pair:E");
|
||||
memory->create(G,ntypes+1,ntypes+1,"pair:G");
|
||||
memory->create(alpha,ntypes+1,ntypes+1,"pair:alpha");
|
||||
memory->create(gamman,ntypes+1,ntypes+1,"pair:gamman");
|
||||
memory->create(muS,ntypes+1,ntypes+1,"pair:muS");
|
||||
memory->create(Ecoh,ntypes+1,ntypes+1,"pair:Ecoh");
|
||||
memory->create(kR,ntypes+1,ntypes+1,"pair:kR");
|
||||
memory->create(muR,ntypes+1,ntypes+1,"pair:muR");
|
||||
memory->create(etaR,ntypes+1,ntypes+1,"pair:etaR");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
PairGranDMTRolling::~PairGranDMTRolling()
|
||||
{
|
||||
delete [] E_one;
|
||||
delete [] G_one;
|
||||
delete [] pois;
|
||||
delete [] muS_one;
|
||||
delete [] cor;
|
||||
delete [] alpha_one;
|
||||
delete [] Ecoh_one;
|
||||
delete [] kR_one;
|
||||
delete [] muR_one;
|
||||
delete [] etaR_one;
|
||||
//TODO: Make all this work with standard pair coeff type commands.
|
||||
//Also these should not be in the destructor.
|
||||
memory->destroy(E);
|
||||
memory->destroy(G);
|
||||
memory->destroy(alpha);
|
||||
memory->destroy(gamman);
|
||||
memory->destroy(muS);
|
||||
memory->destroy(Ecoh);
|
||||
memory->destroy(kR);
|
||||
memory->destroy(muR);
|
||||
memory->destroy(etaR);
|
||||
}
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranDMTRolling::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,ii,jj,inum,jnum;
|
||||
int itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz,nx,ny,nz;
|
||||
double radi,radj,radsum,rsq,r,rinv,rsqinv,R,a;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
|
||||
double wr1,wr2,wr3;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double kn, kt, k_Q, k_R, eta_N, eta_T, eta_Q, eta_R;
|
||||
double Fhz, Fdamp, Fdmt, Fne, Fntot, Fscrit, Frcrit;
|
||||
double overlap;
|
||||
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
|
||||
double relrot1,relrot2,relrot3,vrl1,vrl2,vrl3,vrlmag,vrlmaginv;
|
||||
double rollmag, rolldotn, scalefac;
|
||||
double fr, fr1, fr2, fr3;
|
||||
double signtwist, magtwist, magtortwist, Mtcrit;
|
||||
double fs,fs1,fs2,fs3,roll1,roll2,roll3,torroll1,torroll2,torroll3;
|
||||
double tortwist1, tortwist2, tortwist3;
|
||||
double shrmag,rsht;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
int *touch,**firsttouch;
|
||||
double *shear,*allshear,**firstshear;
|
||||
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = vflag_fdotr = 0;
|
||||
|
||||
int shearupdate = 1;
|
||||
if (update->setupflag) shearupdate = 0;
|
||||
|
||||
// update rigid body info for owned & ghost atoms if using FixRigid masses
|
||||
// body[i] = which body atom I is in, -1 if none
|
||||
// mass_body = mass of each rigid body
|
||||
|
||||
if (fix_rigid && neighbor->ago == 0){
|
||||
int tmp;
|
||||
int *body = (int *) fix_rigid->extract("body",tmp);
|
||||
double *mass_body = (double *) fix_rigid->extract("masstotal",tmp);
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(mass_rigid);
|
||||
nmax = atom->nmax;
|
||||
memory->create(mass_rigid,nmax,"pair:mass_rigid");
|
||||
}
|
||||
int nlocal = atom->nlocal;
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (body[i] >= 0) mass_rigid[i] = mass_body[body[i]];
|
||||
else mass_rigid[i] = 0.0;
|
||||
comm->forward_comm_pair(this);
|
||||
}
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double **omega = atom->omega;
|
||||
double **torque = atom->torque;
|
||||
double *radius = atom->radius;
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = list->listhistory->firstneigh;
|
||||
firstshear = list->listhistory->firstdouble;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
touch = firsttouch[i];
|
||||
allshear = firstshear[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
jtype = type[j];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum){
|
||||
// unset non-touching neighbors
|
||||
touch[jj] = 0;
|
||||
shear = &allshear[nsheardim*jj];
|
||||
for (int k = 0; k < nsheardim; k++)
|
||||
shear[k] = 0.0;
|
||||
} else {
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
R = radi*radj/(radi+radj);
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz; //v_R . n
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
//****************************************
|
||||
//Normal force = Hertzian contact + DMT + damping
|
||||
//****************************************
|
||||
overlap = radsum - r;
|
||||
a = sqrt(R*overlap);
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
Fhz = kn*overlap;
|
||||
|
||||
//Damping (based on Tsuji et al)
|
||||
if (normaldamp == BRILLIANTOV) eta_N = a*meff*gamman[itype][jtype];
|
||||
else if (normaldamp == TSUJI) eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
//DMT
|
||||
Fdmt = -4*MY_PI*Ecoh[itype][jtype]*R;
|
||||
|
||||
Fne = Fhz + Fdmt;
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
//****************************************
|
||||
//Tangential force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
// tangential component
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
//Luding Gran Matt 2008, v10,p235 suggests correcting radi and radj by subtracting
|
||||
//delta/2, i.e. instead of radi, use distance to center of contact point?
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// relative tangential velocities
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
touch[jj] = 1;
|
||||
shear = &allshear[nsheardim*jj];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// Rotate and update shear displacements.
|
||||
// See e.g. eq. 17 of Luding, Gran. Matter 2008, v10,p235
|
||||
if (shearupdate) {
|
||||
rsht = shear[0]*nx + shear[1]*ny + shear[2]*nz;
|
||||
if (fabs(rsht) < EPSILON) rsht = 0;
|
||||
if (rsht > 0){
|
||||
scalefac = shrmag/(shrmag - rsht); //if rhst == shrmag, contacting pair has rotated 90 deg. in one step, in which case you deserve a crash!
|
||||
shear[0] -= rsht*nx;
|
||||
shear[1] -= rsht*ny;
|
||||
shear[2] -= rsht*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[0] *= scalefac;
|
||||
shear[1] *= scalefac;
|
||||
shear[2] *= scalefac;
|
||||
}
|
||||
//Update shear history
|
||||
shear[0] += vtr1*dt;
|
||||
shear[1] += vtr2*dt;
|
||||
shear[2] += vtr3*dt;
|
||||
}
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
// following Zhao and Marshall Phys Fluids v20, p043302 (2008)
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N; //Based on discussion in Marshall; eta_T can also be an independent parameter
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1; //eq 26
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Fscrit = muS[itype][jtype] * fabs(Fne);
|
||||
// For JKR, use eq 43 of Marshall. For DMT, use Fne instead
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
//shear[0] = (Fcrit/fs) * (shear[0] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[1] = (Fcrit/fs) * (shear[1] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[2] = (Fcrit/fs) * (shear[2] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
shear[0] = -1.0/kt*(Fscrit*fs1/fs + eta_T*vtr1); //Same as above, but simpler (check!)
|
||||
shear[1] = -1.0/kt*(Fscrit*fs2/fs + eta_T*vtr2);
|
||||
shear[2] = -1.0/kt*(Fscrit*fs3/fs + eta_T*vtr3);
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = 0.0;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Rolling force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
relrot1 = omega[i][0] - omega[j][0];
|
||||
relrot2 = omega[i][1] - omega[j][1];
|
||||
relrot3 = omega[i][2] - omega[j][2];
|
||||
|
||||
// rolling velocity, see eq. 31 of Wang et al, Particuology v 23, p 49 (2015)
|
||||
// This is different from the Marshall papers, which use the Bagi/Kuhn formulation
|
||||
// for rolling velocity (see Wang et al for why the latter is wrong)
|
||||
vrl1 = R*(relrot2*nz - relrot3*ny); //- 0.5*((radj-radi)/radsum)*vtr1;
|
||||
vrl2 = R*(relrot3*nx - relrot1*nz); //- 0.5*((radj-radi)/radsum)*vtr2;
|
||||
vrl3 = R*(relrot1*ny - relrot2*nx); //- 0.5*((radj-radi)/radsum)*vtr3;
|
||||
vrlmag = sqrt(vrl1*vrl1+vrl2*vrl2+vrl3*vrl3);
|
||||
if (vrlmag != 0.0) vrlmaginv = 1.0/vrlmag;
|
||||
else vrlmaginv = 0.0;
|
||||
|
||||
// Rolling displacement
|
||||
rollmag = sqrt(shear[3]*shear[3] + shear[4]*shear[4] + shear[5]*shear[5]);
|
||||
rolldotn = shear[3]*nx + shear[4]*ny + shear[5]*nz;
|
||||
|
||||
if (shearupdate) {
|
||||
if (fabs(rolldotn) < EPSILON) rolldotn = 0;
|
||||
if (rolldotn > 0){ //Rotate into tangential plane
|
||||
scalefac = rollmag/(rollmag - rolldotn);
|
||||
shear[3] -= rolldotn*nx;
|
||||
shear[4] -= rolldotn*ny;
|
||||
shear[5] -= rolldotn*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[3] *= scalefac;
|
||||
shear[4] *= scalefac;
|
||||
shear[5] *= scalefac;
|
||||
}
|
||||
shear[3] += vrl1*dt;
|
||||
shear[4] += vrl2*dt;
|
||||
shear[5] += vrl3*dt;
|
||||
}
|
||||
|
||||
k_R = kR[itype][jtype];
|
||||
if (rollingdamp == INDEP) eta_R = etaR[itype][jtype];
|
||||
else if (rollingdamp == BRILLROLL) eta_R = muR[itype][jtype]*fabs(Fne);
|
||||
fr1 = -k_R*shear[3] - eta_R*vrl1;
|
||||
fr2 = -k_R*shear[4] - eta_R*vrl2;
|
||||
fr3 = -k_R*shear[5] - eta_R*vrl3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Frcrit = muR[itype][jtype] * fabs(Fne);
|
||||
|
||||
fr = sqrt(fr1*fr1 + fr2*fr2 + fr3*fr3);
|
||||
if (fr > Frcrit) {
|
||||
if (rollmag != 0.0) {
|
||||
shear[3] = -1.0/k_R*(Frcrit*fr1/fr + eta_R*vrl1);
|
||||
shear[4] = -1.0/k_R*(Frcrit*fr2/fr + eta_R*vrl2);
|
||||
shear[5] = -1.0/k_R*(Frcrit*fr3/fr + eta_R*vrl3);
|
||||
fr1 *= Frcrit/fr;
|
||||
fr2 *= Frcrit/fr;
|
||||
fr3 *= Frcrit/fr;
|
||||
} else fr1 = fr2 = fr3 = 0.0;
|
||||
}
|
||||
|
||||
|
||||
//****************************************
|
||||
// Twisting torque, including shear history effects
|
||||
//****************************************
|
||||
magtwist = relrot1*nx + relrot2*ny + relrot3*nz; //Omega_T (eq 29 of Marshall)
|
||||
shear[6] += magtwist*dt;
|
||||
k_Q = 0.5*kt*a*a;; //eq 32
|
||||
eta_Q = 0.5*eta_T*a*a;
|
||||
magtortwist = -k_Q*shear[6] - eta_Q*magtwist;//M_t torque (eq 30)
|
||||
|
||||
signtwist = (magtwist > 0) - (magtwist < 0);
|
||||
Mtcrit=TWOTHIRDS*a*Fscrit;//critical torque (eq 44)
|
||||
if (fabs(magtortwist) > Mtcrit){
|
||||
shear[6] = 1.0/k_Q*(Mtcrit*signtwist - eta_Q*magtwist);
|
||||
magtortwist = -Mtcrit * signtwist; //eq 34
|
||||
}
|
||||
|
||||
// Apply forces & torques
|
||||
|
||||
fx = nx*Fntot + fs1;
|
||||
fy = ny*Fntot + fs2;
|
||||
fz = nz*Fntot + fs3;
|
||||
|
||||
f[i][0] += fx;
|
||||
f[i][1] += fy;
|
||||
f[i][2] += fz;
|
||||
|
||||
tor1 = ny*fs3 - nz*fs2;
|
||||
tor2 = nz*fs1 - nx*fs3;
|
||||
tor3 = nx*fs2 - ny*fs1;
|
||||
|
||||
torque[i][0] -= radi*tor1;
|
||||
torque[i][1] -= radi*tor2;
|
||||
torque[i][2] -= radi*tor3;
|
||||
|
||||
tortwist1 = magtortwist * nx;
|
||||
tortwist2 = magtortwist * ny;
|
||||
tortwist3 = magtortwist * nz;
|
||||
|
||||
torque[i][0] += tortwist1;
|
||||
torque[i][1] += tortwist2;
|
||||
torque[i][2] += tortwist3;
|
||||
|
||||
torroll1 = R*(ny*fr3 - nz*fr2); //n cross fr
|
||||
torroll2 = R*(nz*fr1 - nx*fr3);
|
||||
torroll3 = R*(nx*fr2 - ny*fr1);
|
||||
|
||||
torque[i][0] += torroll1;
|
||||
torque[i][1] += torroll2;
|
||||
torque[i][2] += torroll3;
|
||||
|
||||
if (force->newton_pair || j < nlocal) {
|
||||
f[j][0] -= fx;
|
||||
f[j][1] -= fy;
|
||||
f[j][2] -= fz;
|
||||
|
||||
torque[j][0] -= radj*tor1;
|
||||
torque[j][1] -= radj*tor2;
|
||||
torque[j][2] -= radj*tor3;
|
||||
|
||||
torque[j][0] -= tortwist1;
|
||||
torque[j][1] -= tortwist2;
|
||||
torque[j][2] -= tortwist3;
|
||||
|
||||
torque[j][0] -= torroll1;
|
||||
torque[j][1] -= torroll2;
|
||||
torque[j][2] -= torroll3;
|
||||
}
|
||||
if (evflag) ev_tally_xyz(i,j,nlocal,0,
|
||||
0.0,0.0,fx,fy,fz,delx,dely,delz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranDMTRolling::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 6) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
if (narg < 8*ntypes) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
E_one = new double[ntypes+1];
|
||||
G_one = new double[ntypes+1];
|
||||
pois = new double[ntypes+1];
|
||||
muS_one = new double[ntypes+1];
|
||||
cor = new double[ntypes+1];
|
||||
alpha_one = new double[ntypes+1];
|
||||
Ecoh_one = new double[ntypes+1];
|
||||
kR_one = new double[ntypes+1];
|
||||
muR_one = new double[ntypes+1];
|
||||
etaR_one = new double[ntypes+1];
|
||||
|
||||
for (int i=0; i < ntypes;i++){
|
||||
E_one[i+1] = force->numeric(FLERR, arg[i]);
|
||||
G_one[i+1] = force->numeric(FLERR, arg[ntypes+i]);
|
||||
muS_one[i+1] = force->numeric(FLERR, arg[2*ntypes+i]);
|
||||
cor[i+1] = force->numeric(FLERR, arg[3*ntypes+i]);
|
||||
Ecoh_one[i+1] = force->numeric(FLERR, arg[4*ntypes+i]);
|
||||
kR_one[i+1] = force->numeric(FLERR, arg[5*ntypes+i]);
|
||||
muR_one[i+1] = force->numeric(FLERR, arg[6*ntypes+i]);
|
||||
etaR_one[i+1] = force->numeric(FLERR, arg[7*ntypes+i]);
|
||||
}
|
||||
|
||||
//Defaults
|
||||
normaldamp = TSUJI;
|
||||
rollingdamp = INDEP;
|
||||
|
||||
int iarg = 8*ntypes;
|
||||
while (iarg < narg){
|
||||
if (strcmp(arg[iarg],"normaldamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"tsuji") == 0) normaldamp = TSUJI;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) normaldamp = BRILLIANTOV;
|
||||
else error->all(FLERR, "Invalid normal damping model for pair/gran/dmt/rolling");
|
||||
iarg += 2;
|
||||
}
|
||||
else if (strcmp(arg[iarg],"rollingdamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"independent") == 0) rollingdamp = INDEP;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) rollingdamp = BRILLROLL;
|
||||
else error->all(FLERR, "Invalid rolling damping model for pair/gran/dmt/rolling");
|
||||
iarg += 2;
|
||||
}
|
||||
else{
|
||||
iarg +=1;
|
||||
}
|
||||
}
|
||||
|
||||
//Derived from inputs
|
||||
for (int i=1; i <= ntypes; i++){
|
||||
pois[i] = E_one[i]/(2.0*G_one[i]) - 1.0;
|
||||
alpha_one[i] = 1.2728-4.2783*cor[i]+11.087*cor[i]*cor[i]-22.348*cor[i]*cor[i]*cor[i]+27.467*cor[i]*cor[i]*cor[i]*cor[i]-18.022*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]+4.8218*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]*cor[i];
|
||||
for (int j=i; j <= ntypes; j++){
|
||||
E[i][j] = E[j][i] = 1/((1-pois[i]*pois[i])/E_one[i]+(1-pois[j]*pois[j])/E_one[j]);
|
||||
G[i][j] = G[j][i] = 1/((2-pois[i])/G_one[i]+(2-pois[j])/G_one[j]);
|
||||
if (normaldamp == TSUJI){
|
||||
alpha[i][j] = alpha[j][i] = sqrt(alpha_one[i]*alpha_one[j]);
|
||||
}
|
||||
else if (normaldamp == BRILLIANTOV){
|
||||
gamman[i][j] = gamman[j][i] = sqrt(cor[i]*cor[j]);
|
||||
}
|
||||
muS[i][j] = muS[j][i] = sqrt(muS_one[i]*muS_one[j]);
|
||||
Ecoh[i][j] = Ecoh[j][i] = sqrt(Ecoh_one[i]*Ecoh_one[j]);
|
||||
kR[i][j] = kR[j][i] = sqrt(kR_one[i]*kR_one[j]);
|
||||
etaR[i][j] = etaR[j][i] = sqrt(etaR_one[i]*etaR_one[j]);
|
||||
muR[i][j] = muR[j][i] = sqrt(muR_one[i]*muR_one[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double PairGranDMTRolling::single(int i, int j, int itype, int jtype,
|
||||
double rsq,
|
||||
double factor_coul, double factor_lj,
|
||||
double &fforce)
|
||||
{
|
||||
double radi,radj,radsum;
|
||||
double r,rinv,rsqinv,delx,dely,delz, nx, ny, nz, R;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3,wr1,wr2,wr3;
|
||||
double overlap, a;
|
||||
double mi,mj,meff,damp,kn,kt;
|
||||
double Fhz,Fdamp,Fdmt,Fne,Fntot,Fscrit;
|
||||
double eta_N,eta_T;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double fs1,fs2,fs3,fs;
|
||||
double shrmag;
|
||||
|
||||
|
||||
double *radius = atom->radius;
|
||||
radi = radius[i];
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum) {
|
||||
fforce = 0.0;
|
||||
svector[0] = svector[1] = svector[2] = svector[3] = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
R = radi*radj/radsum;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
double **v = atom->v;
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
double **x = atom->x;
|
||||
delx = x[i][0] - x[j][0];
|
||||
dely = x[i][1] - x[j][1];
|
||||
delz = x[i][2] - x[j][2];
|
||||
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz;
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// tangential component
|
||||
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
|
||||
double **omega = atom->omega;
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
// NOTE: ensure mass_rigid is current for owned+ghost atoms?
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
|
||||
// normal force = Hertzian contact + normal velocity damping
|
||||
overlap = radsum - r;
|
||||
a = sqrt(R*overlap);
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
Fhz = kn*overlap;
|
||||
|
||||
//Damping (based on Tsuji et al)
|
||||
|
||||
eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
//DMT
|
||||
Fdmt = -4*MY_PI*Ecoh[itype][jtype]*R;
|
||||
|
||||
Fne = Fhz + Fdmt;
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
// relative velocities
|
||||
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
// neighprev = index of found neigh on previous call
|
||||
// search entire jnum list of neighbors of I for neighbor J
|
||||
// start from neighprev, since will typically be next neighbor
|
||||
// reset neighprev to 0 as necessary
|
||||
|
||||
int jnum = list->numneigh[i];
|
||||
int *jlist = list->firstneigh[i];
|
||||
double *allshear = list->listhistory->firstdouble[i];
|
||||
|
||||
for (int jj = 0; jj < jnum; jj++) {
|
||||
neighprev++;
|
||||
if (neighprev >= jnum) neighprev = 0;
|
||||
if (jlist[neighprev] == j) break;
|
||||
}
|
||||
|
||||
double *shear = &allshear[nsheardim*neighprev];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N;
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1;
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
Fscrit= muS[itype][jtype] * fabs(Fne);
|
||||
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
fs *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = fs = 0.0;
|
||||
}
|
||||
|
||||
// set all forces and return no energy
|
||||
|
||||
fforce = Fntot;
|
||||
|
||||
// set single_extra quantities
|
||||
|
||||
svector[0] = fs1;
|
||||
svector[1] = fs2;
|
||||
svector[2] = fs3;
|
||||
svector[3] = fs;
|
||||
svector[4] = vn1;
|
||||
svector[5] = vn2;
|
||||
svector[6] = vn3;
|
||||
svector[7] = vt1;
|
||||
svector[8] = vt2;
|
||||
svector[9] = vt3;
|
||||
return 0.0;
|
||||
}
|
||||
@ -1,915 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pair_gran_hooke_history_multi.h"
|
||||
#include "atom.h"
|
||||
#include "atom_vec.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
#include "fix_neigh_history.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neigh_request.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define BIG 1.0e20
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairGranHookeHistoryMulti::PairGranHookeHistoryMulti(LAMMPS *lmp) : Pair(lmp)
|
||||
{
|
||||
single_enable = 1;
|
||||
no_virial_fdotr_compute = 1;
|
||||
history = 1;
|
||||
fix_history = NULL;
|
||||
|
||||
single_extra = 10;
|
||||
svector = new double[10];
|
||||
|
||||
neighprev = 0;
|
||||
|
||||
nmax = 0;
|
||||
mass_rigid = NULL;
|
||||
|
||||
// set comm size needed by this Pair if used with fix rigid
|
||||
|
||||
comm_forward = 1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairGranHookeHistoryMulti::~PairGranHookeHistoryMulti()
|
||||
{
|
||||
delete [] svector;
|
||||
if (fix_history) modify->delete_fix("NEIGH_HISTORY");
|
||||
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
memory->destroy(cutsq);
|
||||
|
||||
memory->destroy(cut);
|
||||
memory->destroy(kn);
|
||||
memory->destroy(kt);
|
||||
memory->destroy(gamman);
|
||||
memory->destroy(gammat);
|
||||
memory->destroy(xmu);
|
||||
memory->destroy(dampflag);
|
||||
|
||||
delete [] onerad_dynamic;
|
||||
delete [] onerad_frozen;
|
||||
delete [] maxrad_dynamic;
|
||||
delete [] maxrad_frozen;
|
||||
}
|
||||
memory->destroy(mass_rigid);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,ii,jj,inum,jnum,itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
|
||||
double radi,radj,radsum,rsq,r,rinv,rsqinv;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
|
||||
double wr1,wr2,wr3;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
|
||||
double fn,fs,fs1,fs2,fs3;
|
||||
double shrmag,rsht;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
int *touch,**firsttouch;
|
||||
double *shear,*allshear,**firstshear;
|
||||
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = vflag_fdotr = 0;
|
||||
|
||||
int shearupdate = 1;
|
||||
if (update->setupflag) shearupdate = 0;
|
||||
|
||||
// update rigid body info for owned & ghost atoms if using FixRigid masses
|
||||
// body[i] = which body atom I is in, -1 if none
|
||||
// mass_body = mass of each rigid body
|
||||
|
||||
if (fix_rigid && neighbor->ago == 0) {
|
||||
int tmp;
|
||||
int *body = (int *) fix_rigid->extract("body",tmp);
|
||||
double *mass_body = (double *) fix_rigid->extract("masstotal",tmp);
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(mass_rigid);
|
||||
nmax = atom->nmax;
|
||||
memory->create(mass_rigid,nmax,"pair:mass_rigid");
|
||||
}
|
||||
int nlocal = atom->nlocal;
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (body[i] >= 0) mass_rigid[i] = mass_body[body[i]];
|
||||
else mass_rigid[i] = 0.0;
|
||||
comm->forward_comm_pair(this);
|
||||
}
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
int *type = atom->type;
|
||||
double **omega = atom->omega;
|
||||
double **torque = atom->torque;
|
||||
double *radius = atom->radius;
|
||||
double *rmass = atom->rmass;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = fix_history->firstflag;
|
||||
firstshear = fix_history->firstvalue;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
itype = type[i];
|
||||
radi = radius[i];
|
||||
touch = firsttouch[i];
|
||||
allshear = firstshear[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
jtype = type[j];
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum) {
|
||||
|
||||
// unset non-touching neighbors
|
||||
|
||||
touch[jj] = 0;
|
||||
shear = &allshear[3*jj];
|
||||
shear[0] = 0.0;
|
||||
shear[1] = 0.0;
|
||||
shear[2] = 0.0;
|
||||
|
||||
} else {
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
vnnr = vr1*delx + vr2*dely + vr3*delz;
|
||||
vn1 = delx*vnnr * rsqinv;
|
||||
vn2 = dely*vnnr * rsqinv;
|
||||
vn3 = delz*vnnr * rsqinv;
|
||||
|
||||
// tangential component
|
||||
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]) * rinv;
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]) * rinv;
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]) * rinv;
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
// normal forces = Hookian contact + normal velocity damping
|
||||
|
||||
damp = meff*gamman[itype][jtype]*vnnr*rsqinv;
|
||||
ccel = kn[itype][jtype]*(radsum-r)*rinv - damp;
|
||||
|
||||
// relative velocities
|
||||
|
||||
vtr1 = vt1 - (delz*wr2-dely*wr3);
|
||||
vtr2 = vt2 - (delx*wr3-delz*wr1);
|
||||
vtr3 = vt3 - (dely*wr1-delx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
|
||||
touch[jj] = 1;
|
||||
shear = &allshear[3*jj];
|
||||
|
||||
if (shearupdate) {
|
||||
shear[0] += vtr1*dt;
|
||||
shear[1] += vtr2*dt;
|
||||
shear[2] += vtr3*dt;
|
||||
}
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// rotate shear displacements
|
||||
|
||||
rsht = shear[0]*delx + shear[1]*dely + shear[2]*delz;
|
||||
rsht *= rsqinv;
|
||||
if (shearupdate) {
|
||||
shear[0] -= rsht*delx;
|
||||
shear[1] -= rsht*dely;
|
||||
shear[2] -= rsht*delz;
|
||||
}
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
|
||||
fs1 = - (kt[itype][jtype]*shear[0] + meff*gammat[itype][jtype]*vtr1);
|
||||
fs2 = - (kt[itype][jtype]*shear[1] + meff*gammat[itype][jtype]*vtr2);
|
||||
fs3 = - (kt[itype][jtype]*shear[2] + meff*gammat[itype][jtype]*vtr3);
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
fn = xmu[itype][jtype] * fabs(ccel*r);
|
||||
|
||||
if (fs > fn) {
|
||||
if (shrmag != 0.0) {
|
||||
shear[0] = (fn/fs) * (shear[0] +
|
||||
meff*gammat[itype][jtype]*vtr1/kt[itype][jtype]) -
|
||||
meff*gammat[itype][jtype]*vtr1/kt[itype][jtype];
|
||||
shear[1] = (fn/fs) * (shear[1] +
|
||||
meff*gammat[itype][jtype]*vtr2/kt[itype][jtype]) -
|
||||
meff*gammat[itype][jtype]*vtr2/kt[itype][jtype];
|
||||
shear[2] = (fn/fs) * (shear[2] +
|
||||
meff*gammat[itype][jtype]*vtr3/kt[itype][jtype]) -
|
||||
meff*gammat[itype][jtype]*vtr3/kt[itype][jtype];
|
||||
fs1 *= fn/fs;
|
||||
fs2 *= fn/fs;
|
||||
fs3 *= fn/fs;
|
||||
} else fs1 = fs2 = fs3 = 0.0;
|
||||
}
|
||||
|
||||
// forces & torques
|
||||
|
||||
fx = delx*ccel + fs1;
|
||||
fy = dely*ccel + fs2;
|
||||
fz = delz*ccel + fs3;
|
||||
f[i][0] += fx;
|
||||
f[i][1] += fy;
|
||||
f[i][2] += fz;
|
||||
|
||||
tor1 = rinv * (dely*fs3 - delz*fs2);
|
||||
tor2 = rinv * (delz*fs1 - delx*fs3);
|
||||
tor3 = rinv * (delx*fs2 - dely*fs1);
|
||||
torque[i][0] -= radi*tor1;
|
||||
torque[i][1] -= radi*tor2;
|
||||
torque[i][2] -= radi*tor3;
|
||||
|
||||
if (newton_pair || j < nlocal) {
|
||||
f[j][0] -= fx;
|
||||
f[j][1] -= fy;
|
||||
f[j][2] -= fz;
|
||||
torque[j][0] -= radj*tor1;
|
||||
torque[j][1] -= radj*tor2;
|
||||
torque[j][2] -= radj*tor3;
|
||||
}
|
||||
|
||||
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
|
||||
0.0,0.0,fx,fy,fz,delx,dely,delz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
memory->create(setflag,n+1,n+1,"pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
memory->create(cutsq,n+1,n+1,"pair:cutsq");
|
||||
memory->create(cut,n+1,n+1,"pair:cut");
|
||||
memory->create(kn,n+1,n+1,"pair:kn");
|
||||
memory->create(kt,n+1,n+1,"pair:kt");
|
||||
memory->create(gamman,n+1,n+1,"pair:gamman");
|
||||
memory->create(gammat,n+1,n+1,"pair:gammat");
|
||||
memory->create(xmu,n+1,n+1,"pair:xmu");
|
||||
memory->create(dampflag,n+1,n+1,"pair:dampflag");
|
||||
|
||||
onerad_dynamic = new double[n+1];
|
||||
onerad_frozen = new double[n+1];
|
||||
maxrad_dynamic = new double[n+1];
|
||||
maxrad_frozen = new double[n+1];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg != 1) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
if (strcmp(arg[0],"NULL") == 0 ) cut_global = -1.0;
|
||||
else cut_global = force->numeric(FLERR,arg[0]);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
if (allocated) {
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) cut[i][j] = cut_global;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type pairs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::coeff(int narg, char **arg)
|
||||
{
|
||||
if (narg < 8 || narg > 9)
|
||||
error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
|
||||
if (!allocated) allocate();
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double kn_one = force->numeric(FLERR,arg[2]);
|
||||
double kt_one;
|
||||
if (strcmp(arg[3],"NULL") == 0) kt_one = kn_one * 2.0/7.0;
|
||||
else kt_one = force->numeric(FLERR,arg[3]);
|
||||
|
||||
double gamman_one = force->numeric(FLERR,arg[4]);
|
||||
double gammat_one;
|
||||
if (strcmp(arg[5],"NULL") == 0) gammat_one = 0.5 * gamman_one;
|
||||
else gammat_one = force->numeric(FLERR,arg[5]);
|
||||
|
||||
double xmu_one = force->numeric(FLERR,arg[6]);
|
||||
int dampflag_one = force->inumeric(FLERR,arg[7]);
|
||||
if (dampflag_one == 0) gammat_one = 0.0;
|
||||
|
||||
if (kn_one < 0.0 || kt_one < 0.0 || gamman_one < 0.0 || gammat_one < 0.0 ||
|
||||
xmu_one < 0.0 || xmu_one > 10000.0 || dampflag_one < 0 || dampflag_one > 1)
|
||||
error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
// convert Kn and Kt from pressure units to force/distance^2
|
||||
kn_one /= force->nktv2p;
|
||||
kt_one /= force->nktv2p;
|
||||
|
||||
double cut_one = cut_global;
|
||||
if (narg==9) {
|
||||
if (strcmp(arg[8],"NULL") == 0) cut_one = -1.0;
|
||||
else cut_one = force->numeric(FLERR,arg[8]);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
kn[i][j] = kn_one;
|
||||
kt[i][j] = kt_one;
|
||||
gamman[i][j] = gamman_one;
|
||||
gammat[i][j] = gammat_one;
|
||||
xmu[i][j] = xmu_one;
|
||||
dampflag[i][j] = dampflag_one;
|
||||
cut[i][j] = cut_one;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::init_style()
|
||||
{
|
||||
int i;
|
||||
|
||||
// error and warning checks
|
||||
|
||||
if (!atom->radius_flag || !atom->rmass_flag)
|
||||
error->all(FLERR,"Pair granular requires atom attributes radius, rmass");
|
||||
if (comm->ghost_velocity == 0)
|
||||
error->all(FLERR,"Pair granular requires ghost atoms store velocity");
|
||||
|
||||
// need a granular neigh list
|
||||
|
||||
int irequest = neighbor->request(this,instance_me);
|
||||
neighbor->requests[irequest]->size = 1;
|
||||
if (history) neighbor->requests[irequest]->history = 1;
|
||||
|
||||
dt = update->dt;
|
||||
|
||||
// if shear history is stored:
|
||||
// if first init, create Fix needed for storing shear history
|
||||
|
||||
if (history && fix_history == NULL) {
|
||||
char dnumstr[16];
|
||||
sprintf(dnumstr,"%d",3);
|
||||
char **fixarg = new char*[4];
|
||||
fixarg[0] = (char *) "NEIGH_HISTORY";
|
||||
fixarg[1] = (char *) "all";
|
||||
fixarg[2] = (char *) "NEIGH_HISTORY";
|
||||
fixarg[3] = dnumstr;
|
||||
modify->add_fix(4,fixarg,1);
|
||||
delete [] fixarg;
|
||||
fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1];
|
||||
fix_history->pair = this;
|
||||
}
|
||||
|
||||
// check for FixFreeze and set freeze_group_bit
|
||||
|
||||
for (i = 0; i < modify->nfix; i++)
|
||||
if (strcmp(modify->fix[i]->style,"freeze") == 0) break;
|
||||
if (i < modify->nfix) freeze_group_bit = modify->fix[i]->groupbit;
|
||||
else freeze_group_bit = 0;
|
||||
|
||||
// check for FixRigid so can extract rigid body masses
|
||||
|
||||
fix_rigid = NULL;
|
||||
for (i = 0; i < modify->nfix; i++)
|
||||
if (modify->fix[i]->rigid_flag) break;
|
||||
if (i < modify->nfix) fix_rigid = modify->fix[i];
|
||||
|
||||
// check for FixPour and FixDeposit so can extract particle radii
|
||||
|
||||
int ipour;
|
||||
for (ipour = 0; ipour < modify->nfix; ipour++)
|
||||
if (strcmp(modify->fix[ipour]->style,"pour") == 0) break;
|
||||
if (ipour == modify->nfix) ipour = -1;
|
||||
|
||||
int idep;
|
||||
for (idep = 0; idep < modify->nfix; idep++)
|
||||
if (strcmp(modify->fix[idep]->style,"deposit") == 0) break;
|
||||
if (idep == modify->nfix) idep = -1;
|
||||
|
||||
// set maxrad_dynamic and maxrad_frozen for each type
|
||||
// include future FixPour and FixDeposit particles as dynamic
|
||||
|
||||
int itype;
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
onerad_dynamic[i] = onerad_frozen[i] = 0.0;
|
||||
if (ipour >= 0) {
|
||||
itype = i;
|
||||
onerad_dynamic[i] =
|
||||
*((double *) modify->fix[ipour]->extract("radius",itype));
|
||||
}
|
||||
if (idep >= 0) {
|
||||
itype = i;
|
||||
onerad_dynamic[i] =
|
||||
*((double *) modify->fix[idep]->extract("radius",itype));
|
||||
}
|
||||
}
|
||||
|
||||
double *radius = atom->radius;
|
||||
int *mask = atom->mask;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (mask[i] & freeze_group_bit)
|
||||
onerad_frozen[type[i]] = MAX(onerad_frozen[type[i]],radius[i]);
|
||||
else
|
||||
onerad_dynamic[type[i]] = MAX(onerad_dynamic[type[i]],radius[i]);
|
||||
|
||||
MPI_Allreduce(&onerad_dynamic[1],&maxrad_dynamic[1],atom->ntypes,
|
||||
MPI_DOUBLE,MPI_MAX,world);
|
||||
MPI_Allreduce(&onerad_frozen[1],&maxrad_frozen[1],atom->ntypes,
|
||||
MPI_DOUBLE,MPI_MAX,world);
|
||||
|
||||
// set fix which stores history info
|
||||
|
||||
if (history) {
|
||||
int ifix = modify->find_fix("NEIGH_HISTORY");
|
||||
if (ifix < 0) error->all(FLERR,"Could not find pair fix neigh history ID");
|
||||
fix_history = (FixNeighHistory *) modify->fix[ifix];
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::init_one(int i, int j)
|
||||
{
|
||||
if (setflag[i][j] == 0) {
|
||||
kn[i][j] = mix_stiffness(kn[i][i],kn[j][j]);
|
||||
kt[i][j] = mix_stiffness(kt[i][i],kt[j][j]);
|
||||
gamman[i][j] = mix_damping(gamman[i][i],gamman[j][j]);
|
||||
gammat[i][j] = mix_damping(gammat[i][i],gammat[j][j]);
|
||||
xmu[i][j] = mix_friction(xmu[i][i],xmu[j][j]);
|
||||
|
||||
dampflag[i][j] = 0;
|
||||
if (dampflag[i][i] || dampflag[j][j]) dampflag[i][j] = 1;
|
||||
|
||||
}
|
||||
|
||||
kn[j][i] = kn[i][j];
|
||||
kt[j][i] = kt[i][j];
|
||||
gamman[j][i] = gamman[i][j];
|
||||
gammat[j][i] = gammat[i][j];
|
||||
xmu[j][i] = xmu[i][j];
|
||||
dampflag[j][i] = dampflag[i][j];
|
||||
|
||||
double cutoff = cut[i][j];
|
||||
|
||||
// It is likely that cut[i][j] at this point is still 0.0. This can happen when
|
||||
// there is a future fix_pour after the current run. A cut[i][j] = 0.0 creates
|
||||
// problems because neighbor.cpp uses min(cut[i][j]) to decide on the bin size
|
||||
// To avoid this issue,for cases involving cut[i][j] = 0.0 (possible only
|
||||
// if there is no current information about radius/cutoff of type i and j).
|
||||
// we assign cutoff = min(cut[i][j]) for i,j such that cut[i][j] > 0.0.
|
||||
|
||||
if (cut[i][j] < 0.0) {
|
||||
if (((maxrad_dynamic[i] > 0.0) && (maxrad_dynamic[j] > 0.0)) || ((maxrad_dynamic[i] > 0.0) && (maxrad_frozen[j] > 0.0)) ||
|
||||
((maxrad_frozen[i] > 0.0) && (maxrad_dynamic[j] > 0.0))) { // radius info about both i and j exist
|
||||
cutoff = maxrad_dynamic[i]+maxrad_dynamic[j];
|
||||
cutoff = MAX(cutoff,maxrad_frozen[i]+maxrad_dynamic[j]);
|
||||
cutoff = MAX(cutoff,maxrad_dynamic[i]+maxrad_frozen[j]);
|
||||
}
|
||||
else { // radius info about either i or j does not exist (i.e. not present and not about to get poured; set to largest value to not interfere with neighbor list)
|
||||
double cutmax = 0.0;
|
||||
for (int k = 1; k <= atom->ntypes; k++) {
|
||||
cutmax = MAX(cutmax,2.0*maxrad_dynamic[k]);
|
||||
cutmax = MAX(cutmax,2.0*maxrad_frozen[k]);
|
||||
}
|
||||
cutoff = cutmax;
|
||||
}
|
||||
}
|
||||
return cutoff;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::write_restart(FILE *fp)
|
||||
{
|
||||
write_restart_settings(fp);
|
||||
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
fwrite(&setflag[i][j],sizeof(int),1,fp);
|
||||
if (setflag[i][j]) {
|
||||
fwrite(&kn[i][j],sizeof(double),1,fp);
|
||||
fwrite(&kt[i][j],sizeof(double),1,fp);
|
||||
fwrite(&gamman[i][j],sizeof(double),1,fp);
|
||||
fwrite(&gammat[i][j],sizeof(double),1,fp);
|
||||
fwrite(&xmu[i][j],sizeof(double),1,fp);
|
||||
fwrite(&dampflag[i][j],sizeof(int),1,fp);
|
||||
fwrite(&cut[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::read_restart(FILE *fp)
|
||||
{
|
||||
read_restart_settings(fp);
|
||||
allocate();
|
||||
|
||||
int i,j;
|
||||
int me = comm->me;
|
||||
for (i = 1; i <= atom->ntypes; i++) {
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
|
||||
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
|
||||
if (setflag[i][j]) {
|
||||
if (me == 0) {
|
||||
fread(&kn[i][j],sizeof(double),1,fp);
|
||||
fread(&kt[i][j],sizeof(double),1,fp);
|
||||
fread(&gamman[i][j],sizeof(double),1,fp);
|
||||
fread(&gammat[i][j],sizeof(double),1,fp);
|
||||
fread(&xmu[i][j],sizeof(double),1,fp);
|
||||
fread(&dampflag[i][j],sizeof(int),1,fp);
|
||||
fread(&cut[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
MPI_Bcast(&kn[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&kt[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&gamman[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&gammat[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&xmu[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&dampflag[i][j],1,MPI_INT,0,world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::write_restart_settings(FILE *fp)
|
||||
{
|
||||
fwrite(&cut_global,sizeof(double),1,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::read_restart_settings(FILE *fp)
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
fread(&cut_global,sizeof(double),1,fp);
|
||||
}
|
||||
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::reset_dt()
|
||||
{
|
||||
dt = update->dt;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::single(int i, int j, int itype, int jtype,
|
||||
double rsq,
|
||||
double factor_coul, double factor_lj,
|
||||
double &fforce)
|
||||
{
|
||||
double radi,radj,radsum;
|
||||
double r,rinv,rsqinv,delx,dely,delz;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3,wr1,wr2,wr3;
|
||||
double mi,mj,meff,damp,ccel;
|
||||
double vtr1,vtr2,vtr3,vrel,shrmag,rsht;
|
||||
double fs1,fs2,fs3,fs,fn;
|
||||
|
||||
double *radius = atom->radius;
|
||||
radi = radius[i];
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
if (rsq >= radsum*radsum) {
|
||||
fforce = 0.0;
|
||||
for (int m = 0; m < single_extra; m++) svector[m] = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
double **v = atom->v;
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
double **x = atom->x;
|
||||
delx = x[i][0] - x[j][0];
|
||||
dely = x[i][1] - x[j][1];
|
||||
delz = x[i][2] - x[j][2];
|
||||
|
||||
vnnr = vr1*delx + vr2*dely + vr3*delz;
|
||||
vn1 = delx*vnnr * rsqinv;
|
||||
vn2 = dely*vnnr * rsqinv;
|
||||
vn3 = delz*vnnr * rsqinv;
|
||||
|
||||
// tangential component
|
||||
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
|
||||
double **omega = atom->omega;
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]) * rinv;
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]) * rinv;
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]) * rinv;
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
double *rmass = atom->rmass;
|
||||
int *mask = atom->mask;
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
// NOTE: insure mass_rigid is current for owned+ghost atoms?
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
// normal forces = Hookian contact + normal velocity damping
|
||||
|
||||
damp = meff*gamman[itype][jtype]*vnnr*rsqinv;
|
||||
ccel = kn[itype][jtype]*(radsum-r)*rinv - damp;
|
||||
|
||||
// relative velocities
|
||||
|
||||
vtr1 = vt1 - (delz*wr2-dely*wr3);
|
||||
vtr2 = vt2 - (delx*wr3-delz*wr1);
|
||||
vtr3 = vt3 - (dely*wr1-delx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
// neighprev = index of found neigh on previous call
|
||||
// search entire jnum list of neighbors of I for neighbor J
|
||||
// start from neighprev, since will typically be next neighbor
|
||||
// reset neighprev to 0 as necessary
|
||||
|
||||
int jnum = list->numneigh[i];
|
||||
int *jlist = list->firstneigh[i];
|
||||
double *allshear = fix_history->firstvalue[i];
|
||||
|
||||
for (int jj = 0; jj < jnum; jj++) {
|
||||
neighprev++;
|
||||
if (neighprev >= jnum) neighprev = 0;
|
||||
if (jlist[neighprev] == j) break;
|
||||
}
|
||||
|
||||
double *shear = &allshear[3*neighprev];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// rotate shear displacements
|
||||
|
||||
rsht = shear[0]*delx + shear[1]*dely + shear[2]*delz;
|
||||
rsht *= rsqinv;
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
|
||||
fs1 = - (kt[itype][jtype]*shear[0] + meff*gammat[itype][jtype]*vtr1);
|
||||
fs2 = - (kt[itype][jtype]*shear[1] + meff*gammat[itype][jtype]*vtr2);
|
||||
fs3 = - (kt[itype][jtype]*shear[2] + meff*gammat[itype][jtype]*vtr3);
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
fn = xmu[itype][jtype] * fabs(ccel*r);
|
||||
|
||||
if (fs > fn) {
|
||||
if (shrmag != 0.0) {
|
||||
fs1 *= fn/fs;
|
||||
fs2 *= fn/fs;
|
||||
fs3 *= fn/fs;
|
||||
fs *= fn/fs;
|
||||
} else fs1 = fs2 = fs3 = fs = 0.0;
|
||||
}
|
||||
|
||||
// set force and return no energy
|
||||
|
||||
fforce = ccel;
|
||||
|
||||
// set single_extra quantities
|
||||
|
||||
svector[0] = fs1;
|
||||
svector[1] = fs2;
|
||||
svector[2] = fs3;
|
||||
svector[3] = fs;
|
||||
svector[4] = vn1;
|
||||
svector[5] = vn2;
|
||||
svector[6] = vn3;
|
||||
svector[7] = vt1;
|
||||
svector[8] = vt2;
|
||||
svector[9] = vt3;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int PairGranHookeHistoryMulti::pack_forward_comm(int n, int *list, double *buf,
|
||||
int pbc_flag, int *pbc)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = mass_rigid[j];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranHookeHistoryMulti::unpack_forward_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++)
|
||||
mass_rigid[i] = buf[m++];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::memory_usage()
|
||||
{
|
||||
double bytes = nmax * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
mixing of stiffness
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::mix_stiffness(double kii, double kjj)
|
||||
{
|
||||
return kii*kjj/(kii + kjj);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
mixing of damping
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::mix_damping(double gammaii, double gammajj)
|
||||
{
|
||||
return sqrt(gammaii*gammajj);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
mixing of friction
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairGranHookeHistoryMulti::mix_friction(double xmuii, double xmujj)
|
||||
{
|
||||
return MAX(xmuii,xmujj);
|
||||
}
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(gran/hooke/history/multi,PairGranHookeHistoryMulti)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_GRAN_HOOKE_HISTORY_MULTI_H
|
||||
#define LMP_PAIR_GRAN_HOOKE_HISTORY_MULTI_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairGranHookeHistoryMulti : public Pair {
|
||||
public:
|
||||
PairGranHookeHistoryMulti(class LAMMPS *);
|
||||
virtual ~PairGranHookeHistoryMulti();
|
||||
virtual void compute(int, int);
|
||||
virtual void settings(int, char **);
|
||||
virtual void coeff(int, char **); // Made Virtual by IS Oct 7 2017
|
||||
void init_style();
|
||||
double init_one(int, int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void write_restart_settings(FILE *);
|
||||
void read_restart_settings(FILE *);
|
||||
void reset_dt();
|
||||
virtual double single(int, int, int, int, double, double, double, double &);
|
||||
int pack_forward_comm(int, int *, double *, int, int *);
|
||||
void unpack_forward_comm(int, int, double *);
|
||||
double memory_usage();
|
||||
|
||||
protected:
|
||||
double cut_global;
|
||||
double **kn,**kt,**gamman,**gammat,**xmu,**cut;
|
||||
int **dampflag;
|
||||
double dt;
|
||||
int freeze_group_bit;
|
||||
int history;
|
||||
|
||||
int neighprev;
|
||||
double *onerad_dynamic,*onerad_frozen;
|
||||
double *maxrad_dynamic,*maxrad_frozen;
|
||||
|
||||
class FixNeighHistory *fix_history;
|
||||
|
||||
// storage of rigid body masses for use in granular interactions
|
||||
|
||||
class Fix *fix_rigid; // ptr to rigid body fix, NULL if none
|
||||
double *mass_rigid; // rigid mass for owned+ghost atoms
|
||||
int nmax; // allocated size of mass_rigid
|
||||
|
||||
virtual void allocate(); // Made Virtual by IS Oct 7 2017
|
||||
|
||||
private:
|
||||
double mix_stiffness(double kii, double kjj);
|
||||
double mix_damping(double gammaii, double gammajj);
|
||||
double mix_friction(double xmuii, double xmujj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
E: Incorrect args for pair coefficients
|
||||
|
||||
Self-explanatory. Check the input script or data file.
|
||||
|
||||
E: Pair granular requires atom attributes radius, rmass
|
||||
|
||||
The atom style defined does not have these attributes.
|
||||
|
||||
E: Pair granular requires ghost atoms store velocity
|
||||
|
||||
Use the comm_modify vel yes command to enable this.
|
||||
|
||||
E: Pair granular with shear history requires newton pair off
|
||||
|
||||
This is a current restriction of the implementation of pair
|
||||
granular styles with history.
|
||||
|
||||
E: Could not find pair fix ID
|
||||
|
||||
A fix is created internally by the pair style to store shear
|
||||
history information. You cannot delete it.
|
||||
|
||||
*/
|
||||
@ -1,763 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pair_gran_jkr_rolling.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "force.h"
|
||||
#include "fix.h"
|
||||
#include "fix_neigh_history.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "comm.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "math_const.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define ONETHIRD 0.33333333333333333
|
||||
#define TWOTHIRDS 0.66666666666666666
|
||||
#define POW6ONE 0.550321208149104 //6^(-1/3)
|
||||
#define POW6TWO 0.30285343213869 //6^(-2/3)
|
||||
|
||||
#define EPSILON 1e-10
|
||||
|
||||
enum {TSUJI, BRILLIANTOV};
|
||||
enum {INDEP, BRILLROLL};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairGranJKRRolling::PairGranJKRRolling(LAMMPS *lmp) :
|
||||
PairGranHookeHistory(lmp, 7)
|
||||
{
|
||||
E_one = NULL;
|
||||
G_one = NULL;
|
||||
pois = NULL;
|
||||
muS_one = NULL;
|
||||
cor = NULL;
|
||||
alpha_one = NULL;
|
||||
Ecoh_one = NULL;
|
||||
kR_one = NULL;
|
||||
muR_one = NULL;
|
||||
etaR_one = NULL;
|
||||
int ntypes = atom->ntypes;
|
||||
memory->create(E,ntypes+1,ntypes+1,"pair:E");
|
||||
memory->create(G,ntypes+1,ntypes+1,"pair:G");
|
||||
memory->create(alpha,ntypes+1,ntypes+1,"pair:alpha");
|
||||
memory->create(gamman,ntypes+1,ntypes+1,"pair:gamman");
|
||||
memory->create(muS,ntypes+1,ntypes+1,"pair:muS");
|
||||
memory->create(Ecoh,ntypes+1,ntypes+1,"pair:Ecoh");
|
||||
memory->create(kR,ntypes+1,ntypes+1,"pair:kR");
|
||||
memory->create(muR,ntypes+1,ntypes+1,"pair:muR");
|
||||
memory->create(etaR,ntypes+1,ntypes+1,"pair:etaR");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
PairGranJKRRolling::~PairGranJKRRolling()
|
||||
{
|
||||
delete [] E_one;
|
||||
delete [] G_one;
|
||||
delete [] pois;
|
||||
delete [] muS_one;
|
||||
delete [] cor;
|
||||
delete [] alpha_one;
|
||||
delete [] Ecoh_one;
|
||||
delete [] kR_one;
|
||||
delete [] muR_one;
|
||||
delete [] etaR_one;
|
||||
//TODO: Make all this work with standard pair coeff type commands.
|
||||
//Also these should not be in the destructor.
|
||||
memory->destroy(E);
|
||||
memory->destroy(G);
|
||||
memory->destroy(alpha);
|
||||
memory->destroy(gamman);
|
||||
memory->destroy(muS);
|
||||
memory->destroy(Ecoh);
|
||||
memory->destroy(kR);
|
||||
memory->destroy(muR);
|
||||
memory->destroy(etaR);
|
||||
}
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairGranJKRRolling::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,ii,jj,inum,jnum;
|
||||
int itype,jtype;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz,nx,ny,nz;
|
||||
double radi,radj,radsum,rsq,r,rinv,rsqinv,R,a;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
|
||||
double wr1,wr2,wr3;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double kn, kt, k_Q, k_R, eta_N, eta_T, eta_Q, eta_R;
|
||||
double Fne, Fdamp, Fntot, Fscrit, Frcrit, F_C, delta_C, delta_Cinv;
|
||||
double overlap, olapsq, olapcubed, sqrtterm, tmp, a0;
|
||||
double keyterm, keyterm2, keyterm3, aovera0, foverFc;
|
||||
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
|
||||
double relrot1,relrot2,relrot3,vrl1,vrl2,vrl3,vrlmag,vrlmaginv;
|
||||
double rollmag, rolldotn, scalefac;
|
||||
double fr, fr1, fr2, fr3;
|
||||
double signtwist, magtwist, magtortwist, Mtcrit;
|
||||
double fs,fs1,fs2,fs3,roll1,roll2,roll3,torroll1,torroll2,torroll3;
|
||||
double tortwist1, tortwist2, tortwist3;
|
||||
double shrmag,rsht;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
int *touch,**firsttouch;
|
||||
double *shear,*allshear,**firstshear;
|
||||
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = vflag_fdotr = 0;
|
||||
|
||||
int shearupdate = 1;
|
||||
if (update->setupflag) shearupdate = 0;
|
||||
|
||||
// update rigid body info for owned & ghost atoms if using FixRigid masses
|
||||
// body[i] = which body atom I is in, -1 if none
|
||||
// mass_body = mass of each rigid body
|
||||
|
||||
if (fix_rigid && neighbor->ago == 0){
|
||||
int tmp;
|
||||
int *body = (int *) fix_rigid->extract("body",tmp);
|
||||
double *mass_body = (double *) fix_rigid->extract("masstotal",tmp);
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(mass_rigid);
|
||||
nmax = atom->nmax;
|
||||
memory->create(mass_rigid,nmax,"pair:mass_rigid");
|
||||
}
|
||||
int nlocal = atom->nlocal;
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (body[i] >= 0) mass_rigid[i] = mass_body[body[i]];
|
||||
else mass_rigid[i] = 0.0;
|
||||
comm->forward_comm_pair(this);
|
||||
}
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double **omega = atom->omega;
|
||||
double **torque = atom->torque;
|
||||
double *radius = atom->radius;
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = fix_history->firstflag;
|
||||
firstshear = fix_history->firstvalue;
|
||||
|
||||
// loop over neighbors of my atoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
touch = firsttouch[i];
|
||||
allshear = firstshear[i];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
jtype = type[j];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
R = radi*radj/(radi+radj);
|
||||
a0 = pow(9.0*M_PI*Ecoh[itype][jtype]*R*R/E[itype][jtype],ONETHIRD);
|
||||
delta_C = 0.5*a0*a0*POW6ONE/R;
|
||||
|
||||
if ((rsq >= radsum*radsum && touch[jj] == 0) ||
|
||||
(rsq >= (radsum+delta_C)*(radsum+delta_C))){
|
||||
// unset non-touching neighbors
|
||||
touch[jj] = 0;
|
||||
shear = &allshear[size_history*jj];
|
||||
for (int k = 0; k < size_history; k++)
|
||||
shear[k] = 0.0;
|
||||
} else {
|
||||
F_C = 3.0*R*M_PI*Ecoh[itype][jtype];
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz; //v_R . n
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
//****************************************
|
||||
//Normal force = JKR-adjusted Hertzian contact + damping
|
||||
//****************************************
|
||||
if (Ecoh[itype][jtype] != 0.0) delta_Cinv = 1.0/delta_C;
|
||||
else delta_Cinv = 1.0;
|
||||
overlap = (radsum - r)*delta_Cinv;
|
||||
olapsq = overlap*overlap;
|
||||
olapcubed = olapsq*overlap;
|
||||
sqrtterm = sqrt(1.0 + olapcubed);
|
||||
tmp = 2.0 + olapcubed + 2.0*sqrtterm;
|
||||
keyterm = pow(tmp,ONETHIRD);
|
||||
keyterm2 = olapsq/keyterm;
|
||||
keyterm3 = sqrt(overlap + keyterm2 + keyterm);
|
||||
aovera0 = POW6TWO * (keyterm3 +
|
||||
sqrt(2.0*overlap - keyterm2 - keyterm + 4.0/keyterm3));// eq 41
|
||||
a = aovera0*a0;
|
||||
foverFc = 4.0*((aovera0*aovera0*aovera0) - pow(aovera0,1.5));//F_ne/F_C (eq 40)
|
||||
|
||||
Fne = F_C*foverFc;
|
||||
|
||||
//Damping
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
if (normaldamp == BRILLIANTOV) eta_N = a*meff*gamman[itype][jtype];
|
||||
else if (normaldamp == TSUJI) eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
//****************************************
|
||||
//Tangential force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
// tangential component
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
//Luding Gran Matt 2008, v10,p235 suggests correcting radi and radj by subtracting
|
||||
//delta/2, i.e. instead of radi, use distance to center of contact point?
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// relative tangential velocities
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
touch[jj] = 1;
|
||||
shear = &allshear[size_history*jj];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// Rotate and update shear displacements.
|
||||
// See e.g. eq. 17 of Luding, Gran. Matter 2008, v10,p235
|
||||
if (shearupdate) {
|
||||
rsht = shear[0]*nx + shear[1]*ny + shear[2]*nz;
|
||||
if (fabs(rsht) < EPSILON) rsht = 0;
|
||||
if (rsht > 0){
|
||||
scalefac = shrmag/(shrmag - rsht); //if rhst == shrmag, contacting pair has rotated 90 deg. in one step, in which case you deserve a crash!
|
||||
shear[0] -= rsht*nx;
|
||||
shear[1] -= rsht*ny;
|
||||
shear[2] -= rsht*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[0] *= scalefac;
|
||||
shear[1] *= scalefac;
|
||||
shear[2] *= scalefac;
|
||||
}
|
||||
//Update shear history
|
||||
shear[0] += vtr1*dt;
|
||||
shear[1] += vtr2*dt;
|
||||
shear[2] += vtr3*dt;
|
||||
}
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
// following Zhao and Marshall Phys Fluids v20, p043302 (2008)
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N; //Based on discussion in Marshall; eta_T can also be an independent parameter
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1; //eq 26
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Fscrit = muS[itype][jtype] * fabs(Fne + 2*F_C);
|
||||
// For JKR, use eq 43 of Marshall. For DMT, use Fne instead
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
//shear[0] = (Fcrit/fs) * (shear[0] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[1] = (Fcrit/fs) * (shear[1] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
//shear[2] = (Fcrit/fs) * (shear[2] + eta_T*vtr1/kt) - eta_T*vtr1/kt;
|
||||
shear[0] = -1.0/kt*(Fscrit*fs1/fs + eta_T*vtr1); //Same as above, but simpler (check!)
|
||||
shear[1] = -1.0/kt*(Fscrit*fs2/fs + eta_T*vtr2);
|
||||
shear[2] = -1.0/kt*(Fscrit*fs3/fs + eta_T*vtr3);
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = 0.0;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Rolling force, including shear history effects
|
||||
//****************************************
|
||||
|
||||
relrot1 = omega[i][0] - omega[j][0];
|
||||
relrot2 = omega[i][1] - omega[j][1];
|
||||
relrot3 = omega[i][2] - omega[j][2];
|
||||
|
||||
// rolling velocity, see eq. 31 of Wang et al, Particuology v 23, p 49 (2015)
|
||||
// This is different from the Marshall papers, which use the Bagi/Kuhn formulation
|
||||
// for rolling velocity (see Wang et al for why the latter is wrong)
|
||||
vrl1 = R*(relrot2*nz - relrot3*ny); //- 0.5*((radj-radi)/radsum)*vtr1;
|
||||
vrl2 = R*(relrot3*nx - relrot1*nz); //- 0.5*((radj-radi)/radsum)*vtr2;
|
||||
vrl3 = R*(relrot1*ny - relrot2*nx); //- 0.5*((radj-radi)/radsum)*vtr3;
|
||||
vrlmag = sqrt(vrl1*vrl1+vrl2*vrl2+vrl3*vrl3);
|
||||
if (vrlmag != 0.0) vrlmaginv = 1.0/vrlmag;
|
||||
else vrlmaginv = 0.0;
|
||||
|
||||
// Rolling displacement
|
||||
rollmag = sqrt(shear[3]*shear[3] + shear[4]*shear[4] + shear[5]*shear[5]);
|
||||
rolldotn = shear[3]*nx + shear[4]*ny + shear[5]*nz;
|
||||
|
||||
if (shearupdate) {
|
||||
if (fabs(rolldotn) < EPSILON) rolldotn = 0;
|
||||
if (rolldotn > 0){ //Rotate into tangential plane
|
||||
scalefac = rollmag/(rollmag - rolldotn);
|
||||
shear[3] -= rolldotn*nx;
|
||||
shear[4] -= rolldotn*ny;
|
||||
shear[5] -= rolldotn*nz;
|
||||
//Also rescale to preserve magnitude
|
||||
shear[3] *= scalefac;
|
||||
shear[4] *= scalefac;
|
||||
shear[5] *= scalefac;
|
||||
}
|
||||
shear[3] += vrl1*dt;
|
||||
shear[4] += vrl2*dt;
|
||||
shear[5] += vrl3*dt;
|
||||
}
|
||||
|
||||
k_R = kR[itype][jtype]*4.0*F_C*pow(aovera0,1.5);
|
||||
if (rollingdamp == INDEP) eta_R = etaR[itype][jtype];
|
||||
else if (rollingdamp == BRILLROLL) eta_R = muR[itype][jtype]*fabs(Fne);
|
||||
fr1 = -k_R*shear[3] - eta_R*vrl1;
|
||||
fr2 = -k_R*shear[4] - eta_R*vrl2;
|
||||
fr3 = -k_R*shear[5] - eta_R*vrl3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
Frcrit = muR[itype][jtype] * fabs(Fne + 2*F_C);
|
||||
|
||||
fr = sqrt(fr1*fr1 + fr2*fr2 + fr3*fr3);
|
||||
if (fr > Frcrit) {
|
||||
if (rollmag != 0.0) {
|
||||
shear[3] = -1.0/k_R*(Frcrit*fr1/fr + eta_R*vrl1);
|
||||
shear[4] = -1.0/k_R*(Frcrit*fr2/fr + eta_R*vrl2);
|
||||
shear[5] = -1.0/k_R*(Frcrit*fr3/fr + eta_R*vrl3);
|
||||
fr1 *= Frcrit/fr;
|
||||
fr2 *= Frcrit/fr;
|
||||
fr3 *= Frcrit/fr;
|
||||
} else fr1 = fr2 = fr3 = 0.0;
|
||||
}
|
||||
|
||||
|
||||
//****************************************
|
||||
// Twisting torque, including shear history effects
|
||||
//****************************************
|
||||
magtwist = relrot1*nx + relrot2*ny + relrot3*nz; //Omega_T (eq 29 of Marshall)
|
||||
shear[6] += magtwist*dt;
|
||||
k_Q = 0.5*kt*a*a;; //eq 32
|
||||
eta_Q = 0.5*eta_T*a*a;
|
||||
magtortwist = -k_Q*shear[6] - eta_Q*magtwist;//M_t torque (eq 30)
|
||||
|
||||
signtwist = (magtwist > 0) - (magtwist < 0);
|
||||
Mtcrit=TWOTHIRDS*a*Fscrit;//critical torque (eq 44)
|
||||
if (fabs(magtortwist) > Mtcrit) {
|
||||
//shear[6] = Mtcrit/k_Q*magtwist/fabs(magtwist);
|
||||
shear[6] = 1.0/k_Q*(Mtcrit*signtwist - eta_Q*magtwist);
|
||||
magtortwist = -Mtcrit * signtwist; //eq 34
|
||||
}
|
||||
|
||||
// Apply forces & torques
|
||||
|
||||
fx = nx*Fntot + fs1;
|
||||
fy = ny*Fntot + fs2;
|
||||
fz = nz*Fntot + fs3;
|
||||
|
||||
f[i][0] += fx;
|
||||
f[i][1] += fy;
|
||||
f[i][2] += fz;
|
||||
|
||||
tor1 = ny*fs3 - nz*fs2;
|
||||
tor2 = nz*fs1 - nx*fs3;
|
||||
tor3 = nx*fs2 - ny*fs1;
|
||||
|
||||
torque[i][0] -= radi*tor1;
|
||||
torque[i][1] -= radi*tor2;
|
||||
torque[i][2] -= radi*tor3;
|
||||
|
||||
tortwist1 = magtortwist * nx;
|
||||
tortwist2 = magtortwist * ny;
|
||||
tortwist3 = magtortwist * nz;
|
||||
|
||||
torque[i][0] += tortwist1;
|
||||
torque[i][1] += tortwist2;
|
||||
torque[i][2] += tortwist3;
|
||||
|
||||
torroll1 = R*(ny*fr3 - nz*fr2); //n cross fr
|
||||
torroll2 = R*(nz*fr1 - nx*fr3);
|
||||
torroll3 = R*(nx*fr2 - ny*fr1);
|
||||
|
||||
torque[i][0] += torroll1;
|
||||
torque[i][1] += torroll2;
|
||||
torque[i][2] += torroll3;
|
||||
|
||||
if (force->newton_pair || j < nlocal) {
|
||||
f[j][0] -= fx;
|
||||
f[j][1] -= fy;
|
||||
f[j][2] -= fz;
|
||||
|
||||
torque[j][0] -= radj*tor1;
|
||||
torque[j][1] -= radj*tor2;
|
||||
torque[j][2] -= radj*tor3;
|
||||
|
||||
torque[j][0] -= tortwist1;
|
||||
torque[j][1] -= tortwist2;
|
||||
torque[j][2] -= tortwist3;
|
||||
|
||||
torque[j][0] -= torroll1;
|
||||
torque[j][1] -= torroll2;
|
||||
torque[j][2] -= torroll3;
|
||||
}
|
||||
if (evflag) ev_tally_xyz(i,j,nlocal,0,
|
||||
0.0,0.0,fx,fy,fz,delx,dely,delz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairGranJKRRolling::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 6) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
int ntypes = atom->ntypes;
|
||||
|
||||
if (narg < 8*ntypes) error->all(FLERR,"Illegal pair_style command");
|
||||
|
||||
E_one = new double[ntypes+1];
|
||||
G_one = new double[ntypes+1];
|
||||
pois = new double[ntypes+1];
|
||||
muS_one = new double[ntypes+1];
|
||||
cor = new double[ntypes+1];
|
||||
alpha_one = new double[ntypes+1];
|
||||
Ecoh_one = new double[ntypes+1];
|
||||
kR_one = new double[ntypes+1];
|
||||
muR_one = new double[ntypes+1];
|
||||
etaR_one = new double[ntypes+1];
|
||||
|
||||
//Defaults
|
||||
normaldamp = TSUJI;
|
||||
rollingdamp = INDEP;
|
||||
|
||||
int iarg = 8*ntypes;
|
||||
while (iarg < narg){
|
||||
if (strcmp(arg[iarg],"normaldamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"tsuji") == 0) normaldamp = TSUJI;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) normaldamp = BRILLIANTOV;
|
||||
else error->all(FLERR, "Invalid normal damping model for pair/gran/dmt/rolling");
|
||||
iarg += 2;
|
||||
}
|
||||
else if (strcmp(arg[iarg],"rollingdamp") == 0){
|
||||
if (iarg+2 > narg) error->all(FLERR, "Invalid pair/gran/dmt/rolling entry");
|
||||
if (strcmp(arg[iarg+1],"independent") == 0) rollingdamp = INDEP;
|
||||
else if (strcmp(arg[iarg+1],"brilliantov") == 0) rollingdamp = BRILLROLL;
|
||||
else error->all(FLERR, "Invalid rolling damping model for pair/gran/dmt/rolling");
|
||||
iarg +=2;
|
||||
}
|
||||
else iarg += 1;
|
||||
}
|
||||
|
||||
for (int i=0; i < ntypes;i++){
|
||||
|
||||
E_one[i+1] = force->numeric(FLERR, arg[i]);
|
||||
G_one[i+1] = force->numeric(FLERR, arg[ntypes+i]);
|
||||
muS_one[i+1] = force->numeric(FLERR, arg[2*ntypes+i]);
|
||||
cor[i+1] = force->numeric(FLERR, arg[3*ntypes+i]);
|
||||
Ecoh_one[i+1] = force->numeric(FLERR, arg[4*ntypes+i]);
|
||||
kR_one[i+1] = force->numeric(FLERR, arg[5*ntypes+i]);
|
||||
muR_one[i+1] = force->numeric(FLERR, arg[6*ntypes+i]);
|
||||
etaR_one[i+1] = force->numeric(FLERR, arg[7*ntypes+i]);
|
||||
}
|
||||
|
||||
//Optional keywords:
|
||||
// normaldamp tsuji, or normaldamp brilliantov
|
||||
// rollingdamp brilliantov
|
||||
|
||||
//Derived from inputs
|
||||
for (int i=1; i <= ntypes; i++){
|
||||
pois[i] = E_one[i]/(2.0*G_one[i]) - 1.0;
|
||||
alpha_one[i] = 1.2728-4.2783*cor[i]+11.087*cor[i]*cor[i]-22.348*cor[i]*cor[i]*cor[i]+27.467*cor[i]*cor[i]*cor[i]*cor[i]-18.022*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]+4.8218*cor[i]*cor[i]*cor[i]*cor[i]*cor[i]*cor[i];
|
||||
for (int j=i; j <= ntypes; j++){
|
||||
E[i][j] = E[j][i] = 1/((1-pois[i]*pois[i])/E_one[i]+(1-pois[j]*pois[j])/E_one[j]);
|
||||
G[i][j] = G[j][i] = 1/((2-pois[i])/G_one[i]+(2-pois[j])/G_one[j]);
|
||||
if (normaldamp == TSUJI){
|
||||
alpha[i][j] = alpha[j][i] = sqrt(alpha_one[i]*alpha_one[j]);
|
||||
}
|
||||
else if (normaldamp == BRILLIANTOV){
|
||||
gamman[i][j] = gamman[j][i] = sqrt(cor[i]*cor[j]);
|
||||
}
|
||||
muS[i][j] = muS[j][i] = sqrt(muS_one[i]*muS_one[j]);
|
||||
Ecoh[i][j] = Ecoh[j][i] = sqrt(Ecoh_one[i]*Ecoh_one[j]);
|
||||
kR[i][j] = kR[j][i] = sqrt(kR_one[i]*kR_one[j]);
|
||||
etaR[i][j] = etaR[j][i] = sqrt(etaR_one[i]*etaR_one[j]);
|
||||
muR[i][j] = muR[j][i] = sqrt(muR_one[i]*muR_one[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double PairGranJKRRolling::single(int i, int j, int itype, int jtype,
|
||||
double rsq,
|
||||
double factor_coul, double factor_lj,
|
||||
double &fforce)
|
||||
{//TODO: update PairGranJKRRolling::single for JKR
|
||||
double radi,radj,radsum;
|
||||
double r,rinv,rsqinv,delx,dely,delz, nx, ny, nz, R;
|
||||
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3,wr1,wr2,wr3;
|
||||
double overlap, a;
|
||||
double mi,mj,meff,damp,kn,kt;
|
||||
double Fdamp,Fne,Fntot,Fscrit;
|
||||
double eta_N,eta_T;
|
||||
double vtr1,vtr2,vtr3,vrel;
|
||||
double fs1,fs2,fs3,fs;
|
||||
double shrmag;
|
||||
double F_C, delta_C, olapsq, olapcubed, sqrtterm, tmp, a0;
|
||||
double keyterm, keyterm2, keyterm3, aovera0, foverFc;
|
||||
|
||||
double *radius = atom->radius;
|
||||
radi = radius[i];
|
||||
radj = radius[j];
|
||||
radsum = radi + radj;
|
||||
|
||||
r = sqrt(rsq);
|
||||
rinv = 1.0/r;
|
||||
rsqinv = 1.0/rsq;
|
||||
R = radi*radj/(radi+radj);
|
||||
a0 = pow(9.0*M_PI*Ecoh[itype][jtype]*R*R/E[itype][jtype],ONETHIRD);
|
||||
delta_C = 0.5*a0*a0*POW6ONE/R;
|
||||
|
||||
int *touch = fix_history->firstflag[i];
|
||||
if ((rsq >= (radsum+delta_C)*(radsum+delta_C) )||
|
||||
(rsq >= radsum*radsum && touch[j])){
|
||||
fforce = 0.0;
|
||||
svector[0] = svector[1] = svector[2] = svector[3] = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// relative translational velocity
|
||||
|
||||
double **v = atom->v;
|
||||
vr1 = v[i][0] - v[j][0];
|
||||
vr2 = v[i][1] - v[j][1];
|
||||
vr3 = v[i][2] - v[j][2];
|
||||
|
||||
// normal component
|
||||
|
||||
double **x = atom->x;
|
||||
delx = x[i][0] - x[j][0];
|
||||
dely = x[i][1] - x[j][1];
|
||||
delz = x[i][2] - x[j][2];
|
||||
|
||||
nx = delx*rinv;
|
||||
ny = dely*rinv;
|
||||
nz = delz*rinv;
|
||||
|
||||
|
||||
vnnr = vr1*nx + vr2*ny + vr3*nz;
|
||||
vn1 = nx*vnnr;
|
||||
vn2 = ny*vnnr;
|
||||
vn3 = nz*vnnr;
|
||||
|
||||
// tangential component
|
||||
|
||||
vt1 = vr1 - vn1;
|
||||
vt2 = vr2 - vn2;
|
||||
vt3 = vr3 - vn3;
|
||||
|
||||
// relative rotational velocity
|
||||
|
||||
double **omega = atom->omega;
|
||||
wr1 = (radi*omega[i][0] + radj*omega[j][0]);
|
||||
wr2 = (radi*omega[i][1] + radj*omega[j][1]);
|
||||
wr3 = (radi*omega[i][2] + radj*omega[j][2]);
|
||||
|
||||
// meff = effective mass of pair of particles
|
||||
// if I or J part of rigid body, use body mass
|
||||
// if I or J is frozen, meff is other particle
|
||||
|
||||
double *rmass = atom->rmass;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
mi = rmass[i];
|
||||
mj = rmass[j];
|
||||
if (fix_rigid) {
|
||||
// NOTE: ensure mass_rigid is current for owned+ghost atoms?
|
||||
if (mass_rigid[i] > 0.0) mi = mass_rigid[i];
|
||||
if (mass_rigid[j] > 0.0) mj = mass_rigid[j];
|
||||
}
|
||||
|
||||
meff = mi*mj / (mi+mj);
|
||||
if (mask[i] & freeze_group_bit) meff = mj;
|
||||
if (mask[j] & freeze_group_bit) meff = mi;
|
||||
|
||||
|
||||
// normal force = JKR
|
||||
F_C = 3.0*R*M_PI*Ecoh[itype][jtype];
|
||||
overlap = radsum - r;
|
||||
olapsq = overlap*overlap;
|
||||
olapcubed = olapsq*olapsq;
|
||||
sqrtterm = sqrt(1.0 + olapcubed);
|
||||
tmp = 2.0 + olapcubed + 2.0*sqrtterm;
|
||||
keyterm = pow(tmp,ONETHIRD);
|
||||
keyterm2 = olapsq/keyterm;
|
||||
keyterm3 = sqrt(overlap + keyterm2 + keyterm);
|
||||
aovera0 = POW6TWO * (keyterm3 +
|
||||
sqrt(2.0*overlap - keyterm2 - keyterm + 4.0/keyterm3));// eq 41
|
||||
a = aovera0*a0;
|
||||
foverFc = 4.0*((aovera0*aovera0*aovera0) - pow(aovera0,1.5));//F_ne/F_C (eq 40)
|
||||
|
||||
Fne = F_C*foverFc;
|
||||
|
||||
//Damping
|
||||
kn = 4.0/3.0*E[itype][jtype]*a;
|
||||
if (normaldamp == BRILLIANTOV) eta_N = a*meff*gamman[itype][jtype];
|
||||
else if (normaldamp == TSUJI) eta_N=alpha[itype][jtype]*sqrt(meff*kn);
|
||||
|
||||
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
|
||||
|
||||
Fntot = Fne + Fdamp;
|
||||
|
||||
// relative velocities
|
||||
|
||||
vtr1 = vt1 - (nz*wr2-ny*wr3);
|
||||
vtr2 = vt2 - (nx*wr3-nz*wr1);
|
||||
vtr3 = vt3 - (ny*wr1-nx*wr2);
|
||||
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
|
||||
vrel = sqrt(vrel);
|
||||
|
||||
// shear history effects
|
||||
// neighprev = index of found neigh on previous call
|
||||
// search entire jnum list of neighbors of I for neighbor J
|
||||
// start from neighprev, since will typically be next neighbor
|
||||
// reset neighprev to 0 as necessary
|
||||
|
||||
int jnum = list->numneigh[i];
|
||||
int *jlist = list->firstneigh[i];
|
||||
double *allshear = fix_history->firstvalue[i];
|
||||
|
||||
for (int jj = 0; jj < jnum; jj++) {
|
||||
neighprev++;
|
||||
if (neighprev >= jnum) neighprev = 0;
|
||||
if (jlist[neighprev] == j) break;
|
||||
}
|
||||
|
||||
double *shear = &allshear[size_history*neighprev];
|
||||
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
|
||||
shear[2]*shear[2]);
|
||||
|
||||
// tangential forces = shear + tangential velocity damping
|
||||
kt=8.0*G[itype][jtype]*a;
|
||||
|
||||
eta_T = eta_N;
|
||||
fs1 = -kt*shear[0] - eta_T*vtr1;
|
||||
fs2 = -kt*shear[1] - eta_T*vtr2;
|
||||
fs3 = -kt*shear[2] - eta_T*vtr3;
|
||||
|
||||
// rescale frictional displacements and forces if needed
|
||||
|
||||
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
|
||||
Fscrit= muS[itype][jtype] * fabs(Fne + 2*F_C);
|
||||
|
||||
if (fs > Fscrit) {
|
||||
if (shrmag != 0.0) {
|
||||
fs1 *= Fscrit/fs;
|
||||
fs2 *= Fscrit/fs;
|
||||
fs3 *= Fscrit/fs;
|
||||
fs *= Fscrit/fs;
|
||||
} else fs1 = fs2 = fs3 = fs = 0.0;
|
||||
}
|
||||
|
||||
// set all forces and return no energy
|
||||
|
||||
fforce = Fntot;
|
||||
|
||||
// set single_extra quantities
|
||||
|
||||
svector[0] = fs1;
|
||||
svector[1] = fs2;
|
||||
svector[2] = fs3;
|
||||
svector[3] = fs;
|
||||
svector[4] = vn1;
|
||||
svector[5] = vn2;
|
||||
svector[6] = vn3;
|
||||
svector[7] = vt1;
|
||||
svector[8] = vt2;
|
||||
svector[9] = vt3;
|
||||
return 0.0;
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(gran/jkr/rolling,PairGranJKRRolling)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_GRAN_JKR_ROLLING_H
|
||||
#define LMP_PAIR_GRAN_JKR_ROLLING_H
|
||||
|
||||
#include "pair_gran_hooke_history.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairGranJKRRolling : public PairGranHookeHistory {
|
||||
public:
|
||||
PairGranJKRRolling(class LAMMPS *);
|
||||
virtual ~PairGranJKRRolling();
|
||||
virtual void compute(int, int);
|
||||
void settings(int, char **); //Eventually set this through coeff method so that user can specify a particular i-j set of coefficients
|
||||
double single(int, int, int, int, double, double, double, double &);
|
||||
double *E_one, *G_one, *pois, *muS_one, *cor, *alpha_one, *Ecoh_one, *kR_one, *muR_one, *etaR_one; //Public so as to be accessible to fix/wall/gran
|
||||
private:
|
||||
double **E, **G, **alpha, **muS, **Ecoh, **kR, **muR, **etaR, **gamman;
|
||||
int normaldamp, rollingdamp;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,87 +0,0 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(gran/jkr/rolling/multi,PairGranJKRRollingMulti)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_GRAN_JKR_ROLLING_MULTI_H
|
||||
#define LMP_PAIR_GRAN_JKR_ROLLING_MULTI_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairGranJKRRollingMulti : public Pair {
|
||||
public:
|
||||
PairGranJKRRollingMulti(class LAMMPS *);
|
||||
virtual ~PairGranJKRRollingMulti();
|
||||
virtual void compute(int, int);
|
||||
virtual void settings(int, char **);
|
||||
virtual void coeff(int, char **); // Made Virtual by IS Oct 7 2017
|
||||
void init_style();
|
||||
double init_one(int, int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void write_restart_settings(FILE *);
|
||||
void read_restart_settings(FILE *);
|
||||
void reset_dt();
|
||||
virtual double single(int, int, int, int, double, double, double, double &);
|
||||
int pack_forward_comm(int, int *, double *, int, int *);
|
||||
void unpack_forward_comm(int, int, double *);
|
||||
double memory_usage();
|
||||
|
||||
protected:
|
||||
double cut_global;
|
||||
double **E,**G,**alpha,**gamman,**muS,**Ecoh,**kR,**muR,**etaR,**cut;
|
||||
int **normaldamp, **rollingdamp;
|
||||
double dt;
|
||||
int freeze_group_bit;
|
||||
int history;
|
||||
|
||||
int neighprev;
|
||||
double *onerad_dynamic,*onerad_frozen;
|
||||
double *maxrad_dynamic,*maxrad_frozen;
|
||||
|
||||
class FixNeighHistory *fix_history;
|
||||
|
||||
// storage of rigid body masses for use in granular interactions
|
||||
|
||||
class Fix *fix_rigid; // ptr to rigid body fix, NULL if none
|
||||
double *mass_rigid; // rigid mass for owned+ghost atoms
|
||||
int nmax; // allocated size of mass_rigid
|
||||
|
||||
virtual void allocate(); // Made Virtual by IS Oct 7 2017
|
||||
|
||||
private:
|
||||
double mix_stiffnessE(double Eii, double Ejj, double Gii, double Gjj);
|
||||
double mix_stiffnessG(double Eii, double Ejj, double Gii, double Gjj);
|
||||
double mix_geom(double valii, double valjj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,107 +0,0 @@
|
||||
/* ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(granular/multi,PairGranularMulti)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_GRANULAR_MULTI_H
|
||||
#define LMP_PAIR_GRANULAR_MULTI_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairGranularMulti : public Pair {
|
||||
public:
|
||||
PairGranularMulti(class LAMMPS *);
|
||||
virtual ~PairGranularMulti();
|
||||
virtual void compute(int, int);
|
||||
virtual void settings(int, char **);
|
||||
virtual void coeff(int, char **);
|
||||
void init_style();
|
||||
double init_one(int, int);
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void reset_dt();
|
||||
virtual double single(int, int, int, int, double, double, double, double &);
|
||||
int pack_forward_comm(int, int *, double *, int, int *);
|
||||
void unpack_forward_comm(int, int, double *);
|
||||
double memory_usage();
|
||||
|
||||
protected:
|
||||
double cut_global;
|
||||
double dt;
|
||||
int freeze_group_bit;
|
||||
int use_history;
|
||||
|
||||
int neighprev;
|
||||
double *onerad_dynamic,*onerad_frozen;
|
||||
double *maxrad_dynamic,*maxrad_frozen;
|
||||
double **cut;
|
||||
|
||||
class FixNeighHistory *fix_history;
|
||||
|
||||
// storage of rigid body masses for use in granular interactions
|
||||
|
||||
class Fix *fix_rigid; // ptr to rigid body fix, NULL if none
|
||||
double *mass_rigid; // rigid mass for owned+ghost atoms
|
||||
int nmax; // allocated size of mass_rigid
|
||||
|
||||
virtual void allocate();
|
||||
|
||||
private:
|
||||
int size_history;
|
||||
|
||||
//Models
|
||||
int **normal, **damping, **tangential, **roll, **twist;
|
||||
|
||||
//History flags
|
||||
int tangential_history, roll_history, twist_history;
|
||||
|
||||
//Indices of history entries
|
||||
int tangential_history_index;
|
||||
int roll_history_index;
|
||||
int twist_history_index;
|
||||
|
||||
//Per-type coefficients, set in pair coeff command
|
||||
double ***normal_coeffs;
|
||||
double ***tangential_coeffs;
|
||||
double ***roll_coeffs;
|
||||
double ***twist_coeffs;
|
||||
|
||||
//Optional user-specified global cutoff
|
||||
double cutoff_global;
|
||||
|
||||
double mix_stiffnessE(double Eii, double Ejj, double Gii, double Gjj);
|
||||
double mix_stiffnessG(double Eii, double Ejj, double Gii, double Gjj);
|
||||
double mix_geom(double valii, double valjj);
|
||||
double pulloff_distance(double radius, int itype);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user