Updated pair body rounded/polygon and rounded/polyhedron

This commit is contained in:
Trung Nguyen 2018-05-24 23:35:49 -05:00
parent 4308f005ab
commit 4bd4b2a1c7
3 changed files with 105 additions and 42 deletions

View File

@ -848,6 +848,7 @@ int PairBodyRoundedPolygon::vertex_against_edge(int i, int j,
// done with the edges from body j,
// given that vertex ni interacts with only one vertex from one edge of body j
// comment out this break to take into account concave shapes
// break;
@ -955,6 +956,7 @@ int PairBodyRoundedPolygon::vertex_against_edge(int i, int j,
// done with the edges from body j,
// given that vertex ni interacts with only one edge from body j
// comment out this break to take into account concave shapes
// break;
@ -1080,12 +1082,12 @@ int PairBodyRoundedPolygon::compute_distance_to_vertex(int ibody,
// check if x0 (the queried vertex) and xmi (the body's center of mass)
// are on the different sides of the edge
int m = 1;//opposite_sides(xi1, xi2, x0, xmi);
int m = opposite_sides(xi1, xi2, x0, xmi);
if (m == 0) {
// x0 and xmi are on not the opposite sides of the edge
// leave xpi for another edge to detect -- for convex shapes only
// leave xpi for another edge to detect
mode = NONE;

View File

@ -47,7 +47,7 @@ using namespace MathConst;
#define DELTA 10000
#define EPSILON 1e-3
#define MAX_FACE_SIZE 4 // maximum number of vertices per face (same as BodyRoundedPolyhedron)
#define MAX_CONTACTS 16 // for 3D models
#define MAX_CONTACTS 32 // for 3D models
//#define _POLYHEDRON_DEBUG
@ -308,36 +308,8 @@ void PairBodyRoundedPolyhedron::compute(int eflag, int vflag)
// also consider point contacts and line contacts
if (num_contacts > 0) {
double contact_area;
if (num_contacts == 1) {
contact_area = 0;
} else if (num_contacts == 2) {
contact_area = num_contacts * A_ua;
} else {
int m;
double xc[3],dx,dy,dz;
xc[0] = xc[1] = xc[2] = 0;
for (m = 0; m < num_contacts; m++) {
xc[0] += contact_list[m].xi[0];
xc[1] += contact_list[m].xi[1];
xc[2] += contact_list[m].xi[2];
}
xc[0] /= (double)num_contacts;
xc[1] /= (double)num_contacts;
xc[2] /= (double)num_contacts;
contact_area = 0.0;
for (m = 0; m < num_contacts; m++) {
dx = contact_list[m].xi[0] - xc[0];
dy = contact_list[m].xi[1] - xc[1];
dz = contact_list[m].xi[2] - xc[2];
contact_area += (dx*dx + dy*dy + dz*dz);
}
contact_area *= (MY_PI/(double)num_contacts);
}
rescale_cohesive_forces(x, f, torque, contact_list, num_contacts,
contact_area, k_nij, k_naij, facc);
k_nij, k_naij, facc);
}
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,evdwl,0.0,
@ -383,6 +355,8 @@ void PairBodyRoundedPolyhedron::settings(int narg, char **arg)
mu = force->numeric(FLERR,arg[2]);
A_ua = force->numeric(FLERR,arg[3]);
cut_inner = force->numeric(FLERR,arg[4]);
if (A_ua < 0) A_ua = 1;
}
/* ----------------------------------------------------------------------
@ -1381,7 +1355,17 @@ int PairBodyRoundedPolyhedron::interaction_face_to_edge(int ibody,
#endif
} else if (interact == EF_INTERSECT_INSIDE) {
// need to do something here to resolve overlap!!
// p is the intersection between the edge and the face
int jflag = 1;
if (d1 < d2)
pair_force_and_torque(jbody, ibody, xpj1, hi1, d1, contact_dist,
k_n, k_na, shift, x, v, f, torque, angmom,
jflag, energy, facc);
else
pair_force_and_torque(jbody, ibody, xpj2, hi2, d2, contact_dist,
k_n, k_na, shift, x, v, f, torque, angmom,
jflag, energy, facc);
}
return interact;
@ -1661,6 +1645,7 @@ void PairBodyRoundedPolyhedron::contact_forces(int ibody, int jbody,
ft[1] = -c_t * vt2;
ft[2] = -c_t * vt3;
// these are contact forces (F_n, F_t and F_ne) only
// cohesive forces will be scaled by j_a after contact area is computed
// mu * fne = tangential friction deformation during gross sliding
// see Eq. 4, Fraige et al.
@ -1697,13 +1682,49 @@ void PairBodyRoundedPolyhedron::contact_forces(int ibody, int jbody,
void PairBodyRoundedPolyhedron::rescale_cohesive_forces(double** x,
double** f, double** torque, Contact* contact_list, int &num_contacts,
double contact_area, double k_n, double k_na, double* facc)
double k_n, double k_na, double* facc)
{
int m,ibody,jbody;
double delx,dely,delz,fx,fy,fz,R,fpair,r,shift;
double delx,dely,delz,fx,fy,fz,R,fpair,r,shift,contact_area;
int num_unique_contacts = 0;
if (num_contacts == 1) {
num_unique_contacts = 1;
contact_area = 0;
} else if (num_contacts == 2) {
num_unique_contacts = 2;
contact_area = num_contacts * A_ua;
} else {
find_unique_contacts(contact_list, num_contacts);
double xc[3],dx,dy,dz;
xc[0] = xc[1] = xc[2] = 0;
num_unique_contacts = 0;
for (int m = 0; m < num_contacts; m++) {
if (contact_list[m].unique == 0) continue;
xc[0] += contact_list[m].xi[0];
xc[1] += contact_list[m].xi[1];
xc[2] += contact_list[m].xi[2];
num_unique_contacts++;
}
xc[0] /= (double)num_unique_contacts;
xc[1] /= (double)num_unique_contacts;
xc[2] /= (double)num_unique_contacts;
contact_area = 0.0;
for (int m = 0; m < num_contacts; m++) {
if (contact_list[m].unique == 0) continue;
dx = contact_list[m].xi[0] - xc[0];
dy = contact_list[m].xi[1] - xc[1];
dz = contact_list[m].xi[2] - xc[2];
contact_area += (dx*dx + dy*dy + dz*dz);
}
contact_area *= (MY_PI/(double)num_unique_contacts);
}
double j_a = contact_area / (num_contacts * A_ua);
if (j_a < 1.0) j_a = 1.0;
shift = k_na * cut_inner;
for (m = 0; m < num_contacts; m++) {
@ -2302,6 +2323,41 @@ void PairBodyRoundedPolyhedron::total_velocity(double* p, double *xcm,
vi[2] = omega[0]*r[1] - omega[1]*r[0] + vcm[2];
}
/* ----------------------------------------------------------------------
Determine the length of the contact segment, i.e. the separation between
2 contacts, should be extended for 3D models.
------------------------------------------------------------------------- */
double PairBodyRoundedPolyhedron::contact_separation(const Contact& c1,
const Contact& c2)
{
double x1 = 0.5*(c1.xi[0] + c1.xj[0]);
double y1 = 0.5*(c1.xi[1] + c1.xj[1]);
double z1 = 0.5*(c1.xi[2] + c1.xj[2]);
double x2 = 0.5*(c2.xi[0] + c2.xj[0]);
double y2 = 0.5*(c2.xi[1] + c2.xj[1]);
double z2 = 0.5*(c2.xi[2] + c2.xj[2]);
double rsq = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1);
return rsq;
}
/* ----------------------------------------------------------------------
find the number of unique contacts
------------------------------------------------------------------------- */
void PairBodyRoundedPolyhedron::find_unique_contacts(Contact* contact_list, int& num_contacts)
{
int n = num_contacts;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (contact_list[i].unique == 0) continue;
double d = contact_separation(contact_list[i], contact_list[j]);
if (d < EPSILON) contact_list[j].unique = 0;
}
}
}
/* ---------------------------------------------------------------------- */
void PairBodyRoundedPolyhedron::sanity_check()

View File

@ -35,12 +35,13 @@ class PairBodyRoundedPolyhedron : public Pair {
double init_one(int, int);
struct Contact {
int ibody, jbody; // body (i.e. atom) indices (not tags)
int type; // 0 = VERTEX-FACE; 1 = EDGE-EDGE
double fx,fy,fz; // unscaled cohesive forces at contact
double xi[3]; // coordinates of the contact point on ibody
double xj[3]; // coordinates of the contact point on jbody
int ibody, jbody; // body (i.e. atom) indices (not tags)
int type; // 0 = VERTEX-FACE; 1 = EDGE-EDGE
double fx,fy,fz; // unscaled cohesive forces at contact
double xi[3]; // coordinates of the contact point on ibody
double xj[3]; // coordinates of the contact point on jbody
double separation; // contact surface separation
int unique;
};
protected:
@ -124,7 +125,11 @@ class PairBodyRoundedPolyhedron : public Pair {
int jflag, double& energy, double* facc);
void rescale_cohesive_forces(double** x, double** f, double** torque,
Contact* contact_list, int &num_contacts,
double contact_area, double k_n, double k_na, double* facc);
double k_n, double k_na, double* facc);
double contact_separation(const Contact& c1, const Contact& c2);
void find_unique_contacts(Contact* contact_list, int& num_contacts);
void sum_torque(double* xm, double *x, double fx, double fy, double fz, double* torque);
int opposite_sides(double* n, double* x0, double* a, double* b);