Added PairGranular::single method

This commit is contained in:
Dan Stefan Bolintineanu
2019-01-07 16:27:04 -07:00
parent dced4c1fca
commit faa716e348
2 changed files with 231 additions and 87 deletions

View File

@ -61,11 +61,10 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 1;
no_virial_fdotr_compute = 1;
use_history = 1;
fix_history = NULL;
single_extra = 10;
svector = new double[10];
single_extra = 9;
svector = new double[single_extra];
neighprev = 0;
@ -83,6 +82,7 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp)
comm_forward = 1;
use_history = 0;
beyond_contact = 0;
roll_history_index = twist_history_index = 0;
tangential_history_index = -1;
@ -351,7 +351,7 @@ void PairGranular::compute(int eflag, int vflag)
vrel = sqrt(vrel);
// If any history is needed:
if (history_flag){
if (use_history){
touch[jj] = 1;
history = &allhistory[size_history*jj];
}
@ -520,7 +520,9 @@ void PairGranular::compute(int eflag, int vflag)
mu_twist = twist_coeffs[itype][jtype][2];
}
if (twist_history){
history[twist_history_index] += magtwist*dt;
if (historyupdate){
history[twist_history_index] += magtwist*dt;
}
magtortwist = -k_twist*history[twist_history_index] - damp_twist*magtwist;//M_t torque (eq 30)
signtwist = (magtwist > 0) - (magtwist < 0);
Mtcrit = TWOTHIRDS*a*Fscrit;//critical torque (eq 44)
@ -1017,7 +1019,7 @@ void PairGranular::init_style()
error->all(FLERR,"Pair granular requires ghost atoms store velocity");
// Determine whether we need a granular neigh list, how large it needs to be
history_flag = tangential_history || roll_history || twist_history;
use_history = tangential_history || roll_history || twist_history;
size_history = 3*tangential_history + 3*roll_history + twist_history;
//Determine location of tangential/roll/twist histories in array
@ -1038,14 +1040,14 @@ void PairGranular::init_style()
int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->size = 1;
if (history_flag) neighbor->requests[irequest]->history = 1;
if (use_history) neighbor->requests[irequest]->history = 1;
dt = update->dt;
// if history is stored:
// if first init, create Fix needed for storing history
if (history_flag && fix_history == NULL) {
if (use_history && fix_history == NULL) {
char dnumstr[16];
sprintf(dnumstr,"%d",size_history);
char **fixarg = new char*[4];
@ -1294,8 +1296,11 @@ double PairGranular::single(int i, int j, int itype, int jtype,
{
double radi,radj,radsum;
double r,rinv,rsqinv,delx,dely,delz, nx, ny, nz, Reff;
double dR, dR2, sqdR;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3,wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
double relrot1,relrot2,relrot3,vrl1,vrl2,vrl3,vrlmag,vrlmaginv;
double knfac, damp_normal;
double k_tangential, damp_tangential;
@ -1307,8 +1312,6 @@ double PairGranular::single(int i, int j, int itype, int jtype,
double delta, t0, t1, t2, t3, t4, t5, t6;
double sqrt1, sqrt2, sqrt3, sqrt4;
double mi,mj,meff,damp,ccel,tor1,tor2,tor3;
double relrot1,relrot2,relrot3,vrl1,vrl2,vrl3,vrlmag,vrlmaginv;
//Rolling
double k_roll, damp_roll;
@ -1371,21 +1374,27 @@ double PairGranular::single(int i, int j, int itype, int jtype,
// 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;
double *rmass = atom->rmass;
int *mask = atom->mask;
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;
delta = radsum - r;
dR = delta*Reff;
// tangential component
vt1 = vr1 - vn1;
@ -1419,86 +1428,223 @@ double PairGranular::single(int i, int j, int itype, int jtype,
if (mask[i] & freeze_group_bit) meff = mj;
if (mask[j] & freeze_group_bit) meff = mi;
delta = radsum - r;
dR = delta*Reff;
if (normal[itype][jtype] == JKR){
dR2 = dR*dR;
t0 = coh*coh*R2*R2*E;
t1 = PI27SQ*t0;
t2 = 8*dR*dR2*E*E*E;
t3 = 4*dR2*E;
sqrt1 = MAX(0, t0*(t1+2*t2)); //In case of sqrt(0) < 0 due to precision issues
t4 = cbrt(t1+t2+THREEROOT3*M_PI*sqrt(sqrt1));
t5 = t3/t4 + t4/E;
sqrt2 = MAX(0, 2*dR + t5);
t6 = sqrt(sqrt2);
sqrt3 = MAX(0, 4*dR - t5 + SIXROOT6*coh*M_PI*R2/(E*t6));
a = INVROOT6*(t6 + sqrt(sqrt3));
a2 = a*a;
knfac = FOURTHIRDS*E*a;
Fne = knfac*a2/Reff - TWOPI*a2*sqrt(4*coh*E/(M_PI*a));
}
else{
knfac = E; //Hooke
Fne = knfac*delta;
if (normal[itype][jtype] != HOOKE)
Fne *= a;
if (normal[itype][jtype] == DMT)
Fne -= 4*MY_PI*normal_coeffs[itype][jtype][3]*Reff;
}
// 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)
//Consider restricting Hooke to only have 'velocity' as an option for damping?
if (damping[itype][jtype] == VELOCITY){
damp_normal = normal_coeffs[itype][jtype][1];
}
else if (damping[itype][jtype] == VISCOELASTIC){
if (normal[itype][jtype] == HOOKE) a = sqdR = sqrt(dR);
damp_normal = normal_coeffs[itype][jtype][1]*sqdR*meff;
}
else if (damping[itype][jtype] == TSUJI){
damp_normal = normal_coeffs[itype][jtype][1]*sqrt(meff*knfac);
}
Fne = F_C*foverFc;
//Damping
kn = 4.0/3.0*E[itype][jtype]*a;
if (normaldamp[itype][jtype] == BRILLIANTOV) eta_N = a*meff*gamman[itype][jtype];
else if (normaldamp[itype][jtype] == TSUJI) eta_N=alpha[itype][jtype]*sqrt(meff*kn);
Fdamp = -eta_N*vnnr; //F_nd eq 23 and Zhao eq 19
Fdamp = -damp_normal*vnnr;
Fntot = Fne + Fdamp;
// relative velocities
int jnum = list->numneigh[i];
int *jlist = list->firstneigh[i];
double *allhistory, *history;
if (use_history){
allhistory = fix_history->firstvalue[i];
for (int jj = 0; jj < jnum; jj++) {
neighprev++;
if (neighprev >= jnum) neighprev = 0;
if (jlist[neighprev] == j) break;
}
history = &allhistory[size_history*neighprev];
}
//****************************************
//Tangential force, including history effects
//****************************************
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
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);
// 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 *allhistory = fix_history->firstvalue[i];
for (int jj = 0; jj < jnum; jj++) {
neighprev++;
if (neighprev >= jnum) neighprev = 0;
if (jlist[neighprev] == j) break;
Fcrit = fabs(Fne);
if (normal[itype][jtype] == JKR){
F_pulloff = 3*M_PI*coh*Reff;
Fcrit = fabs(Fne + 2*F_pulloff);
}
double *history = &allhistory[3*neighprev];
shrmag = sqrt(history[0]*history[0] + history[1]*history[1] +
history[2]*history[2]);
//------------------------------
//Tangential forces
//------------------------------
k_tangential = tangential_coeffs[itype][jtype][0];
if (normal[itype][jtype] != HOOKE){
k_tangential *= a;
}
damp_tangential = tangential_coeffs[itype][jtype][1]*damp_normal;
// tangential forces = history + tangential velocity damping
kt=8.0*G[itype][jtype]*a;
if (tangential_history[itype][jtype]){
shrmag = sqrt(history[0]*history[0] + history[1]*history[1] +
history[2]*history[2]);
eta_T = eta_N;
fs1 = -kt*history[0] - eta_T*vtr1;
fs2 = -kt*history[1] - eta_T*vtr2;
fs3 = -kt*history[2] - eta_T*vtr3;
// tangential forces = history + tangential velocity damping
fs1 = -k_tangential*history[0] - damp_tangential*vtr1;
fs2 = -k_tangential*history[1] - damp_tangential*vtr2;
fs3 = -k_tangential*history[2] - damp_tangential*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;
// rescale frictional displacements and forces if needed
Fscrit = tangential_coeffs[itype][jtype][2] * Fcrit;
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
if (fs > Fscrit) {
if (shrmag != 0.0) {
history[0] = -1.0/k_tangential*(Fscrit*fs1/fs + damp_tangential*vtr1);
history[1] = -1.0/k_tangential*(Fscrit*fs2/fs + damp_tangential*vtr2);
history[2] = -1.0/k_tangential*(Fscrit*fs3/fs + damp_tangential*vtr3);
fs1 *= Fscrit/fs;
fs2 *= Fscrit/fs;
fs3 *= Fscrit/fs;
} else fs1 = fs2 = fs3 = 0.0;
}
}
else{ //Classic pair gran/hooke (no history)
fs = meff*damp_tangential*vrel;
if (vrel != 0.0) Ft = MIN(Fne,fs) / vrel;
else Ft = 0.0;
fs1 = -Ft*vtr1;
fs2 = -Ft*vtr2;
fs3 = -Ft*vtr3;
}
// set all forces and return no energy
//****************************************
// Rolling resistance
//****************************************
fforce = Fntot;
if (roll[itype][jtype] != NONE){
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 = Reff*(relrot2*nz - relrot3*ny); //- 0.5*((radj-radi)/radsum)*vtr1;
vrl2 = Reff*(relrot3*nx - relrot1*nz); //- 0.5*((radj-radi)/radsum)*vtr2;
vrl3 = Reff*(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;
if (roll_history){
int rhist0 = roll_history_index;
int rhist1 = rhist0 + 1;
int rhist2 = rhist1 + 1;
// Rolling displacement
rollmag = sqrt(history[rhist0]*history[rhist0] +
history[rhist1]*history[rhist1] +
history[rhist2]*history[rhist2]);
rolldotn = history[rhist0]*nx + history[rhist1]*ny + history[rhist2]*nz;
k_roll = roll_coeffs[itype][jtype][0];
damp_roll = roll_coeffs[itype][jtype][1];
fr1 = -k_roll*history[rhist0] - damp_roll*vrl1;
fr2 = -k_roll*history[rhist1] - damp_roll*vrl2;
fr3 = -k_roll*history[rhist2] - damp_roll*vrl3;
// rescale frictional displacements and forces if needed
Frcrit = roll_coeffs[itype][jtype][2] * Fcrit;
fr = sqrt(fr1*fr1 + fr2*fr2 + fr3*fr3);
if (fr > Frcrit) {
if (rollmag != 0.0) {
history[rhist0] = -1.0/k_roll*(Frcrit*fr1/fr + damp_roll*vrl1);
history[rhist1] = -1.0/k_roll*(Frcrit*fr2/fr + damp_roll*vrl2);
history[rhist2] = -1.0/k_roll*(Frcrit*fr3/fr + damp_roll*vrl3);
fr1 *= Frcrit/fr;
fr2 *= Frcrit/fr;
fr3 *= Frcrit/fr;
} else fr1 = fr2 = fr3 = 0.0;
}
}
else{ //
fr = meff*roll_coeffs[itype][jtype][1]*vrlmag;
if (vrlmag != 0.0) fr = MIN(Fne, fr) / vrlmag;
else fr = 0.0;
fr1 = -fr*vrl1;
fr2 = -fr*vrl2;
fr3 = -fr*vrl3;
}
}
//****************************************
// Twisting torque, including history effects
//****************************************
if (twist[itype][jtype] != NONE){
magtwist = relrot1*nx + relrot2*ny + relrot3*nz; //Omega_T (eq 29 of Marshall)
if (twist[itype][jtype] == TWIST_MARSHALL){
k_twist = 0.5*k_tangential*a*a;; //eq 32
damp_twist = 0.5*damp_tangential*a*a;
mu_twist = TWOTHIRDS*a;
}
else{
k_twist = twist_coeffs[itype][jtype][0];
damp_twist = twist_coeffs[itype][jtype][1];
mu_twist = twist_coeffs[itype][jtype][2];
}
if (twist_history){
magtortwist = -k_twist*history[twist_history_index] - damp_twist*magtwist;//M_t torque (eq 30)
signtwist = (magtwist > 0) - (magtwist < 0);
Mtcrit = TWOTHIRDS*a*Fscrit;//critical torque (eq 44)
if (fabs(magtortwist) > Mtcrit) {
history[twist_history_index] = 1.0/k_twist*(Mtcrit*signtwist - damp_twist*magtwist);
magtortwist = -Mtcrit * signtwist; //eq 34
}
}
else{
if (magtwist > 0) magtortwist = -damp_twist*magtwist;
else magtortwist = 0;
}
}
// set single_extra quantities
@ -1506,12 +1652,11 @@ double PairGranular::single(int i, int j, int itype, int jtype,
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;
svector[4] = fr1;
svector[5] = fr2;
svector[6] = fr3;
svector[7] = fr;
svector[8] = magtortwist;
return 0.0;
}

View File

@ -73,7 +73,6 @@ private:
int normal_global, damping_global;
int tangential_global, roll_global, twist_global;
int history_flag;
int tangential_history, roll_history, twist_history;
int tangential_history_index;
int roll_history_index;