From ca8dfd3d7c07ac0560cfe8230e705cc068fa1716 Mon Sep 17 00:00:00 2001 From: sjplimp <sjplimp@f3b2605a-c512-4ea7-a41b-209d697bcdaa> Date: Thu, 20 Oct 2011 14:56:49 +0000 Subject: [PATCH] git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@7146 f3b2605a-c512-4ea7-a41b-209d697bcdaa --- src/SRD/fix_srd.cpp | 1162 +++++++++++++++++++++++---------- src/SRD/fix_srd.h | 52 +- src/atom.cpp | 12 +- src/atom.h | 4 +- src/compute_property_atom.cpp | 428 +++++++++++- src/compute_property_atom.h | 19 +- src/fix_rigid.cpp | 325 ++++++--- src/fix_rigid.h | 11 +- src/read_data.cpp | 99 ++- src/read_data.h | 6 +- src/set.cpp | 136 +++- 11 files changed, 1687 insertions(+), 567 deletions(-) diff --git a/src/SRD/fix_srd.cpp b/src/SRD/fix_srd.cpp index 411beb9c9d..b673b9b7b5 100644 --- a/src/SRD/fix_srd.cpp +++ b/src/SRD/fix_srd.cpp @@ -22,6 +22,8 @@ #include "math_extra.h" #include "atom.h" #include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" #include "group.h" #include "update.h" #include "force.h" @@ -42,7 +44,7 @@ using namespace LAMMPS_NS; using namespace MathConst; enum{SLIP,NOSLIP}; -enum{SPHERE,ELLIPSOID,WALL}; +enum{SPHERE,ELLIPSOID,LINE,TRIANGLE,WALL}; enum{INSIDE_ERROR,INSIDE_WARN,INSIDE_IGNORE}; enum{BIG_MOVE,SRD_MOVE,SRD_ROTATE}; enum{CUBIC_ERROR,CUBIC_WARN}; @@ -50,10 +52,13 @@ enum{SHIFT_NO,SHIFT_YES,SHIFT_POSSIBLE}; enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp -#define INERTIA 0.4 -#define ATOMPERBIN 10 +#define EINERTIA 0.2 // moment of inertia prefactor for ellipsoid + +#define ATOMPERBIN 30 #define BIG 1.0e20 #define VBINSIZE 5 +#define TOLERANCE 0.00001 +#define MAXITER 20 //#define SRD_DEBUG 1 //#define SRD_DEBUG_ATOMID 58 @@ -95,7 +100,7 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) cubictol = 0.01; shiftuser = SHIFT_NO; shiftseed = 0; - streamflag = 1; + tstat = 0; int iarg = 8; while (iarg < narg) { @@ -156,10 +161,10 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) else error->all(FLERR,"Illegal fix srd command"); shiftseed = atoi(arg[iarg+2]); iarg += 3; - } else if (strcmp(arg[iarg],"stream") == 0) { + } else if (strcmp(arg[iarg],"tstat") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command"); - if (strcmp(arg[iarg+1],"yes") == 0) streamflag = 1; - else if (strcmp(arg[iarg+1],"no") == 0) streamflag = 0; + if (strcmp(arg[iarg+1],"no") == 0) tstat = 0; + else if (strcmp(arg[iarg+1],"yes") == 0) tstat = 1; else error->all(FLERR,"Illegal fix srd command"); iarg += 2; } else error->all(FLERR,"Illegal fix srd command"); @@ -168,7 +173,8 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) // error check if (nevery <= 0) error->all(FLERR,"Illegal fix srd command"); - if (bigexist && biggroup < 0) error->all(FLERR,"Could not find fix srd group ID"); + if (bigexist && biggroup < 0) + error->all(FLERR,"Could not find fix srd group ID"); if (gridsrd <= 0.0) error->all(FLERR,"Illegal fix srd command"); if (temperature_srd <= 0.0) error->all(FLERR,"Illegal fix srd command"); if (seed <= 0) error->all(FLERR,"Illegal fix srd command"); @@ -176,7 +182,8 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) if (maxbounceallow < 0) error->all(FLERR,"Illegal fix srd command"); if (lamdaflag && lamda <= 0.0) error->all(FLERR,"Illegal fix srd command"); if (gridsearch <= 0.0) error->all(FLERR,"Illegal fix srd command"); - if (cubictol < 0.0 || cubictol > 1.0) error->all(FLERR,"Illegal fix srd command"); + if (cubictol < 0.0 || cubictol > 1.0) + error->all(FLERR,"Illegal fix srd command"); if ((shiftuser == SHIFT_YES || shiftuser == SHIFT_POSSIBLE) && shiftseed <= 0) error->all(FLERR,"Illegal fix srd command"); @@ -236,6 +243,8 @@ FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) // atom style pointers to particles that store bonus info avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + avec_line = (AtomVecLine *) atom->style_match("line"); + avec_tri = (AtomVecTri *) atom->style_match("tri"); // fix parameters @@ -289,7 +298,8 @@ void FixSRD::init() { // error checks - if (force->newton_pair == 0) error->all(FLERR,"Fix srd requires newton pair on"); + if (force->newton_pair == 0) + error->all(FLERR,"Fix srd requires newton pair on"); if (bigexist && comm->ghost_velocity == 0) error->all(FLERR,"Fix srd requires ghost atoms store velocity"); if (bigexist && collidestyle == NOSLIP && !atom->torque_flag) @@ -319,19 +329,21 @@ void FixSRD::init() fwall = wallfix->fwall; walltrigger = 0.5 * neighbor->skin; if (wallfix->overlap && overlap == 0 && me == 0) - error->warning(FLERR,"Fix SRD walls overlap but fix srd overlap not set"); + error->warning(FLERR, + "Fix SRD walls overlap but fix srd overlap not set"); } } // set change_flags if box size or shape changes - change_size = change_shape = 0; + change_size = change_shape = deformflag = 0; if (domain->nonperiodic == 2) change_size = 1; for (int i = 0; i < modify->nfix; i++) if (modify->fix[i]->box_change) { if (modify->fix[i]->box_change_size) change_size = 1; if (modify->fix[i]->box_change_shape) change_shape = 1; if (strcmp(modify->fix[i]->style,"deform") == 0) { + deformflag = 1; FixDeform *deform = (FixDeform *) modify->fix[i]; if (deform->box_change_shape && deform->remapflag != V_REMAP) error->all(FLERR,"Using fix srd with inconsistent " @@ -339,6 +351,10 @@ void FixSRD::init() } } + if (deformflag && tstat == 0 && me == 0) + error->warning(FLERR, + "Using fix srd with box deformation but no SRD thermostat"); + // parameterize based on current box volume dimension = domain->dimension; @@ -391,7 +407,8 @@ void FixSRD::setup(int vflag) setup_bounds(); if (dist_srd_reneigh < nevery*dt_big*vmax && me == 0) - error->warning(FLERR,"Fix srd SRD moves may trigger frequent reneighboring"); + error->warning(FLERR, + "Fix srd SRD moves may trigger frequent reneighboring"); // setup search bins and search stencil based on these distances @@ -407,6 +424,7 @@ void FixSRD::setup(int vflag) reneighflag = BIG_MOVE; pre_neighbor(); } + /* ---------------------------------------------------------------------- assign SRD particles to bins assign big particles to all bins they overlap @@ -416,6 +434,7 @@ void FixSRD::pre_neighbor() { int i,j,m,ix,iy,iz,jx,jy,jz,ibin,jbin,lo,hi; double rsq,cutbinsq; + double xlamda[3]; // grow SRD per-atom bin arrays if necessary @@ -561,7 +580,8 @@ void FixSRD::pre_neighbor() if (side == 0) { hi = static_cast<int> ((xwall[m]+delta-xblo2)*bininv2x); if (hi < 0) continue; - if (hi >= nbin2x) error->all(FLERR,"Fix SRD: bad search bin assignment"); + if (hi >= nbin2x) error->all(FLERR, + "Fix SRD: bad search bin assignment"); lo = 0; } else { lo = static_cast<int> ((xwall[m]-delta-xblo2)*bininv2x); @@ -583,7 +603,8 @@ void FixSRD::pre_neighbor() if (side == 0) { hi = static_cast<int> ((xwall[m]+delta-yblo2)*bininv2y); if (hi < 0) continue; - if (hi >= nbin2y) error->all(FLERR,"Fix SRD: bad search bin assignment"); + if (hi >= nbin2y) error->all(FLERR, + "Fix SRD: bad search bin assignment"); lo = 0; } else { lo = static_cast<int> ((xwall[m]-delta-yblo2)*bininv2y); @@ -605,7 +626,8 @@ void FixSRD::pre_neighbor() if (side == 0) { hi = static_cast<int> ((xwall[m]+delta-zblo2)*bininv2z); if (hi < 0) continue; - if (hi >= nbin2z) error->all(FLERR,"Fix SRD: bad search bin assignment"); + if (hi >= nbin2z) error->all(FLERR, + "Fix SRD: bad search bin assignment"); lo = 0; } else { lo = static_cast<int> ((xwall[m]-delta-zblo2)*bininv2z); @@ -645,6 +667,7 @@ void FixSRD::pre_neighbor() void FixSRD::post_force(int vflag) { int i,m,ix,iy,iz; + double xlamda[3]; // zero per-timestep stats @@ -765,19 +788,20 @@ void FixSRD::post_force(int vflag) /* ---------------------------------------------------------------------- reset SRD velocities - may perform random shifting by 1/2 bin in each dimension + may perform random shifting by up to 1/2 bin in each dimension called at pre-neighbor stage when all SRDs are now inside my sub-domain - for triclinic, will set mean velocity to box deformation velocity + if tstat, then thermostat SRD particles as well, including streaming effects ------------------------------------------------------------------------- */ void FixSRD::reset_velocities() { int i,j,n,ix,iy,iz,ibin,axis,sign,irandom; - double u[3],vave[3]; - double vx,vy,vz,vsq; - double *vold,*vnew,*xlamda; + double u[3],vsum[3]; + double vx,vy,vz,vsq,tbin,scale; + double *vave,*vnew,*xlamda; + double vstream[3]; - // if requested, perform a dynamic shift + // if requested, perform a dynamic shift of bin positions if (shiftflag) { double *boxlo; @@ -831,39 +855,23 @@ void FixSRD::reset_velocities() if (triclinic) domain->lamda2x(nlocal); - if (triclinic && streamflag) { - double *h_rate = domain->h_rate; - double *h_ratelo = domain->h_ratelo; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - xlamda = x[i]; - v[i][0] -= h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] + - h_rate[4]*xlamda[2] + h_ratelo[0]; - v[i][1] -= h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1]; - v[i][2] -= h_rate[2]*xlamda[2] + h_ratelo[2]; - } - } - // for each bin I have particles contributing to: - // compute ave v and v^2 of particles in that bin + // compute summed v of particles in that bin // if I own the bin, set its random value, else set to 0.0 for (i = 0; i < nbins; i++) { n = 0; - vave[0] = vave[1] = vave[2] = 0.0; + vsum[0] = vsum[1] = vsum[2] = 0.0; for (j = binhead[i]; j >= 0; j = binnext[j]) { - vx = v[j][0]; - vy = v[j][1]; - vz = v[j][2]; - vave[0] += vx; - vave[1] += vy; - vave[2] += vz; + vsum[0] += v[j][0]; + vsum[1] += v[j][1]; + vsum[2] += v[j][2]; n++; } - vbin[i].vave[0] = vave[0]; - vbin[i].vave[1] = vave[1]; - vbin[i].vave[2] = vave[2]; + vbin[i].vsum[0] = vsum[0]; + vbin[i].vsum[1] = vsum[1]; + vbin[i].vsum[2] = vsum[2]; vbin[i].n = n; if (vbin[i].owner) vbin[i].random = random->uniform(); else vbin[i].random = 0.0; @@ -874,24 +882,43 @@ void FixSRD::reset_velocities() if (shifts[shiftflag].commflag) vbin_comm(shiftflag); // for each bin I have particles contributing to: - // reassign particle velocity by rotation around a random axis - // accumulate T_srd for each bin I own - // for triclinic, replace mean velocity with stream velocity + // compute vave over particles in bin + // thermal velocity of each particle = v - vave + // rotate thermal vel of each particle around one of 6 random axes + // add vave back to each particle + // thermostat if requested: + // if no deformation, rescale thermal vel to temperature + // if deformation, rescale thermal vel and change vave to vstream + // these are settings for extra dof_temp, dof_tstat to subtract + // (not sure why these settings work best) + // no deformation, no tstat: dof_temp = 1 + // yes deformation, no tstat: doesn't matter, system will not equilibrate + // no deformation, yes tstat: dof_temp = dof_tstat = 1 + // yes deformation, yes tstat: dof_temp = dof_tstat = 0 + // accumulate final T_srd for each bin I own + + double tfactor = force->mvv2e * mass_srd / (dimension * force->boltz); + int dof_temp = 1; + int dof_tstat; + if (tstat) { + if (deformflag) dof_tstat = dof_temp = 0; + else dof_tstat = 1; + } srd_bin_temp = 0.0; srd_bin_count = 0; if (dimension == 2) axis = 2; + double *h_rate = domain->h_rate; + double *h_ratelo = domain->h_ratelo; for (i = 0; i < nbins; i++) { n = vbin[i].n; if (n == 0) continue; - vold = vbin[i].vave; - vold[0] /= n; - vold[1] /= n; - vold[2] /= n; - - vnew = vold; + vave = vbin[i].vsum; + vave[0] /= n; + vave[1] /= n; + vave[2] /= n; irandom = static_cast<int> (6.0*vbin[i].random); sign = irandom % 2; @@ -900,48 +927,64 @@ void FixSRD::reset_velocities() vsq = 0.0; for (j = binhead[i]; j >= 0; j = binnext[j]) { if (axis == 0) { - u[0] = v[j][0]-vold[0]; - u[1] = sign ? v[j][2]-vold[2] : vold[2]-v[j][2]; - u[2] = sign ? vold[1]-v[j][1] : v[j][1]-vold[1]; + u[0] = v[j][0]-vave[0]; + u[1] = sign ? v[j][2]-vave[2] : vave[2]-v[j][2]; + u[2] = sign ? vave[1]-v[j][1] : v[j][1]-vave[1]; } else if (axis == 1) { - u[1] = v[j][1]-vold[1]; - u[0] = sign ? v[j][2]-vold[2] : vold[2]-v[j][2]; - u[2] = sign ? vold[0]-v[j][0] : v[j][0]-vold[0]; + u[1] = v[j][1]-vave[1]; + u[0] = sign ? v[j][2]-vave[2] : vave[2]-v[j][2]; + u[2] = sign ? vave[0]-v[j][0] : v[j][0]-vave[0]; } else { - u[2] = v[j][2]-vold[2]; - u[1] = sign ? v[j][0]-vold[0] : vold[0]-v[j][0]; - u[0] = sign ? vold[1]-v[j][1] : v[j][1]-vold[1]; + u[2] = v[j][2]-vave[2]; + u[1] = sign ? v[j][0]-vave[0] : vave[0]-v[j][0]; + u[0] = sign ? vave[1]-v[j][1] : v[j][1]-vave[1]; } vsq += u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; - v[j][0] = u[0] + vnew[0]; - v[j][1] = u[1] + vnew[1]; - v[j][2] = u[2] + vnew[2]; + v[j][0] = u[0] + vave[0]; + v[j][1] = u[1] + vave[1]; + v[j][2] = u[2] + vave[2]; } - // sum partial contribution of my particles to T even if I don't own bin - // but only count bin if I own it, so that bin is counted exactly once + if (tstat && n > 1) { + if (deformflag) { + xlamda = vbin[i].xctr; + vstream[0] = h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] + + h_rate[4]*xlamda[2] + h_ratelo[0]; + vstream[1] = h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1]; + vstream[2] = h_rate[2]*xlamda[2] + h_ratelo[2]; + } else { + vstream[0] = vave[0]; + vstream[1] = vave[1]; + vstream[2] = vave[2]; + } - if (n > 1) { - srd_bin_temp += vsq / (n-1); - if (vbin[i].owner) srd_bin_count++; + // tbin = thermal temperature of particles in bin + // scale = scale factor for thermal velocity + + tbin = vsq/(n-dof_tstat) * tfactor; + scale = sqrt(temperature_srd/tbin); + + vsq = 0.0; + for (j = binhead[i]; j >= 0; j = binnext[j]) { + u[0] = (v[j][0] - vave[0]) * scale; + u[1] = (v[j][1] - vave[1]) * scale; + u[2] = (v[j][2] - vave[2]) * scale; + vsq += u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; + v[j][0] = u[0] + vstream[0]; + v[j][1] = u[1] + vstream[1]; + v[j][2] = u[2] + vstream[2]; + } } - } - srd_bin_temp *= force->mvv2e * mass_srd / (dimension * force->boltz); + // sum partial contribution of my particles to T even if I don't own bin + // but only count bin if I own it, so each bin is counted exactly once - if (triclinic && streamflag) { - double *h_rate = domain->h_rate; - double *h_ratelo = domain->h_ratelo; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - xlamda = x[i]; - v[i][0] += h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] + - h_rate[4]*xlamda[2] + h_ratelo[0]; - v[i][1] += h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1]; - v[i][2] += h_rate[2]*xlamda[2] + h_ratelo[2]; - } + if (n > 1) srd_bin_temp += vsq/(n-dof_temp); + if (vbin[i].owner) srd_bin_count++; } + srd_bin_temp *= tfactor; + // rescale any too-large velocities for (i = 0; i < nlocal; i++) @@ -1032,9 +1075,9 @@ void FixSRD::vbin_pack(BinAve *vbin, int n, int *list, double *buf) for (int i = 0; i < n; i++) { j = list[i]; buf[m++] = vbin[j].n; - buf[m++] = vbin[j].vave[0]; - buf[m++] = vbin[j].vave[1]; - buf[m++] = vbin[j].vave[2]; + buf[m++] = vbin[j].vsum[0]; + buf[m++] = vbin[j].vsum[1]; + buf[m++] = vbin[j].vsum[2]; buf[m++] = vbin[j].random; } } @@ -1050,9 +1093,9 @@ void FixSRD::vbin_unpack(double *buf, BinAve *vbin, int n, int *list) for (int i = 0; i < n; i++) { j = list[i]; vbin[j].n += static_cast<int> (buf[m++]); - vbin[j].vave[0] += buf[m++]; - vbin[j].vave[1] += buf[m++]; - vbin[j].vave[2] += buf[m++]; + vbin[j].vsum[0] += buf[m++]; + vbin[j].vsum[1] += buf[m++]; + vbin[j].vsum[2] += buf[m++]; vbin[j].random += buf[m++]; } } @@ -1065,7 +1108,7 @@ void FixSRD::vbin_unpack(double *buf, BinAve *vbin, int n, int *list) void FixSRD::collisions_single() { - int i,j,k,m,type,mbig,ibin,ibounce,inside,collide_flag; + int i,j,k,m,type,nbig,ibin,ibounce,inside,collide_flag,lineside; double dt,t_remain; double norm[3],xscoll[3],xbcoll[3],vsnew[3]; Big *big; @@ -1097,11 +1140,11 @@ void FixSRD::collisions_single() dt = dt_big; while (collide_flag) { - mbig = nbinbig[ibin]; - if (ibounce == 0) ncheck += mbig; + nbig = nbinbig[ibin]; + if (ibounce == 0) ncheck += nbig; collide_flag = 0; - for (m = 0; m < mbig; m++) { + for (m = 0; m < nbig; m++) { k = binbig[ibin][m]; big = &biglist[k]; j = big->index; @@ -1161,17 +1204,11 @@ void FixSRD::collisions_single() } if (collidestyle == SLIP) { - if (type == SPHERE) - slip_sphere(v[i],v[j],norm,vsnew); - else if (type == ELLIPSOID) - slip_ellipsoid(v[i],v[j],x[j],big,xscoll,norm,vsnew); - else - slip_wall(v[i],j,norm,vsnew); + if (type != WALL) slip(v[i],v[j],x[j],big,xscoll,norm,vsnew); + else slip_wall(v[i],j,norm,vsnew); } else { - if (type != WALL) - noslip(v[i],v[j],x[j],big,xscoll,norm,vsnew); - else - noslip_wall(v[i],j,xscoll,norm,vsnew); + if (type != WALL) noslip(v[i],v[j],x[j],big,-1, xscoll,norm,vsnew); + else noslip(v[i],NULL,x[j],big,j,xscoll,norm,vsnew); } if (dimension == 2) vsnew[2] = 0.0; @@ -1222,7 +1259,7 @@ void FixSRD::collisions_single() void FixSRD::collisions_multi() { - int i,j,k,m,type,mbig,ibin,ibounce,inside,jfirst,typefirst; + int i,j,k,m,type,nbig,ibin,ibounce,inside,jfirst,typefirst,jlast; double dt,t_remain,t_first; double norm[3],xscoll[3],xbcoll[3],vsnew[3]; double normfirst[3],xscollfirst[3],xbcollfirst[3]; @@ -1251,22 +1288,31 @@ void FixSRD::collisions_multi() if (nbinbig[ibin] == 0) continue; ibounce = 0; + jlast = -1; dt = dt_big; while (1) { - mbig = nbinbig[ibin]; - if (ibounce == 0) ncheck += mbig; + nbig = nbinbig[ibin]; + if (ibounce == 0) ncheck += nbig; t_first = 0.0; - for (m = 0; m < mbig; m++) { + for (m = 0; m < nbig; m++) { k = binbig[ibin][m]; big = &biglist[k]; j = big->index; + if (j == jlast) continue; type = big->type; - if (type == SPHERE) inside = inside_sphere(x[i],x[j],big); - else if (type == ELLIPSOID) inside = inside_ellipsoid(x[i],x[j],big); - else inside = inside_wall(x[i],j); + if (type == SPHERE) + inside = inside_sphere(x[i],x[j],big); + else if (type == ELLIPSOID) + inside = inside_ellipsoid(x[i],x[j],big); + else if (type == LINE) + inside = inside_line(x[i],x[j],v[i],v[j],big,dt); + else if (type == TRIANGLE) + inside = inside_tri(x[i],x[j],v[i],v[j],big,dt); + else + inside = inside_wall(x[i],j); if (inside) { if (type == SPHERE) @@ -1275,6 +1321,12 @@ void FixSRD::collisions_multi() else if (type == ELLIPSOID) t_remain = collision_ellipsoid_exact(x[i],x[j],v[i],v[j],big, xscoll,xbcoll,norm); + else if (type == LINE) + t_remain = collision_line_exact(x[i],x[j],v[i],v[j],big,dt, + xscoll,xbcoll,norm); + else if (type == TRIANGLE) + t_remain = collision_tri_exact(x[i],x[j],v[i],v[j],big,dt, + xscoll,xbcoll,norm); else t_remain = collision_wall_exact(x[i],j,v[i],xscoll,xbcoll,norm); @@ -1318,7 +1370,7 @@ void FixSRD::collisions_multi() } if (t_first == 0.0) break; - j = jfirst; + j = jlast = jfirst; type = typefirst; xscoll[0] = xscollfirst[0]; xscoll[1] = xscollfirst[1]; @@ -1331,17 +1383,11 @@ void FixSRD::collisions_multi() norm[2] = normfirst[2]; if (collidestyle == SLIP) { - if (type == SPHERE) - slip_sphere(v[i],v[j],norm,vsnew); - else if (type == ELLIPSOID) - slip_ellipsoid(v[i],v[j],x[j],big,xscoll,norm,vsnew); - else - slip_wall(v[i],j,norm,vsnew); + if (type != WALL) slip(v[i],v[j],x[j],big,xscoll,norm,vsnew); + else slip_wall(v[i],j,norm,vsnew); } else { - if (type != WALL) - noslip(v[i],v[j],x[j],big,xscoll,norm,vsnew); - else - noslip_wall(v[i],j,xscoll,norm,vsnew); + if (type != WALL) noslip(v[i],v[j],x[j],big,-1,xscoll,norm,vsnew); + else noslip(v[i],NULL,x[j],big,j,xscoll,norm,vsnew); } if (dimension == 2) vsnew[2] = 0.0; @@ -1420,6 +1466,276 @@ int FixSRD::inside_ellipsoid(double *xs, double *xb, Big *big) return 0; } +/* ---------------------------------------------------------------------- + check if SRD particle S is inside line big particle B + collision only possible if: + S starts on positive side of infinite line, + which means it will collide with outside of rigid body made of lines + since line segments have outward normals, + when vector from first to last point is crossed with +z axis + S ends on negative side of infinite line + unlike most other inside() routines, then calculate exact collision: + solve for collision pt along infinite line + collision if pt is within endpoints of B +------------------------------------------------------------------------- */ + +int FixSRD::inside_line(double *xs, double *xb, double *vs, double *vb, + Big *big, double dt_step) +{ + double pmc0[2],pmc1[2],n0[2],n1[2]; + double n1_n0[2],pmc1_pmc0[2]; + + // 1 and 2 = start and end of timestep + // pmc = P - C, where P = position of S, C = position of B + // n = normal to line = [-sin(theta),cos(theta)], theta = orientation of B + // (P-C) dot N = side of line that S is on + // side0 = -1,0,1 for which side of line B that S is on at start of step + // side1 = -1,0,1 for which side of line B that S is on at end of step + + xs1[0] = xs[0]; + xs1[1] = xs[1]; + xb1[0] = xb[0]; + xb1[1] = xb[1]; + + xs0[0] = xs1[0] - dt_step*vs[0]; + xs0[1] = xs1[1] - dt_step*vs[1]; + xb0[0] = xb1[0] - dt_step*vb[0]; + xb0[1] = xb1[1] - dt_step*vb[1]; + + theta1 = big->theta; + theta0 = theta1 - dt_step*big->omega[2]; + + pmc0[0] = xs0[0] - xb0[0]; + pmc0[1] = xs0[1] - xb0[1]; + n0[0] = sin(theta0); + n0[1] = -cos(theta0); + + pmc1[0] = xs1[0] - xb1[0]; + pmc1[1] = xs1[1] - xb1[1]; + n1[0] = sin(theta1); + n1[1] = -cos(theta1); + + double side0 = pmc0[0]*n0[0] + pmc0[1]*n0[1]; + double side1 = pmc1[0]*n1[0] + pmc1[1]*n1[1]; + + if (side0 <= 0.0 || side1 >= 0.0) return 0; + + // solve for time t (0 to 1) at which moving particle + // crosses infinite moving/rotating line + + // Newton-Raphson solve of full non-linear parametric equation + + tfraction = newton_raphson(0.0,1.0); + + // quadratic equation solve of approximate parametric equation + + /* + n1_n0[0] = n1[0]-n0[0]; n1_n0[1] = n1[1]-n0[1]; + pmc1_pmc0[0] = pmc1[0]-pmc0[0]; pmc1_pmc0[1] = pmc1[1]-pmc0[1]; + + double a = pmc1_pmc0[0]*n1_n0[0] + pmc1_pmc0[1]*n1_n0[1]; + double b = pmc1_pmc0[0]*n0[0] + pmc1_pmc0[1]*n0[1] + + n1_n0[0]*pmc0[0] + n1_n0[1]*pmc0[1]; + double c = pmc0[0]*n0[0] + pmc0[1]*n0[1]; + + if (a == 0.0) { + double dot0 = pmc0[0]*n0[0] + pmc0[1]*n0[1]; + double dot1 = pmc1[0]*n0[0] + pmc1[1]*n0[1]; + double root = -dot0 / (dot1 - dot0); + //printf("Linear root: %g %g\n",root,tfraction); + tfraction = root; + + } else { + + double term = sqrt(b*b - 4.0*a*c); + double root1 = (-b + term) / (2.0*a); + double root2 = (-b - term) / (2.0*a); + + //printf("ABC vecs: %g %g: %g %g\n", + // pmc1_pmc0[0],pmc1_pmc0[1],n1_n0[0],n1_n0[1]); + //printf("ABC vecs: %g %g: %g %g: %g %g %g\n", + // n0[0],n0[1],n1[0],n1[1],theta0,theta1,big->omega[2]); + //printf("ABC root: %g %g %g: %g %g %g\n",a,b,c,root1,root2,tfraction); + + if (0.0 <= root1 && root1 <= 1.0) tfraction = root1; + else if (0.0 <= root2 && root2 <= 1.0) tfraction = root2; + else error->one(FLERR,"Bad quadratic solve for particle/line collision"); + } + */ + + // check if collision pt is within line segment at collision time + + xsc[0] = xs0[0] + tfraction*(xs1[0]-xs0[0]); + xsc[1] = xs0[1] + tfraction*(xs1[1]-xs0[1]); + xbc[0] = xb0[0] + tfraction*(xb1[0]-xb0[0]); + xbc[1] = xb0[1] + tfraction*(xb1[1]-xb0[1]); + double delx = xsc[0] - xbc[0]; + double dely = xsc[1] - xbc[1]; + double rsq = delx*delx + dely*dely; + if (rsq > 0.25*big->length*big->length) return 0; + + //nbc[0] = n0[0] + tfraction*(n1[0]-n0[0]); + //nbc[1] = n0[1] + tfraction*(n1[1]-n0[1]); + + nbc[0] = sin(theta0 + tfraction*(theta1-theta0)); + nbc[1] = -cos(theta0 + tfraction*(theta1-theta0)); + + return 1; +} + +/* ---------------------------------------------------------------------- + check if SRD particle S is inside triangle big particle B + collision only possible if: + S starts on positive side of triangle plane, + which means it will collide with outside of rigid body made of tris + since triangles have outward normals, + S ends on negative side of triangle plane + unlike most other inside() routines, then calculate exact collision: + solve for collision pt on triangle plane + collision if pt is inside triangle B +------------------------------------------------------------------------- */ + +int FixSRD::inside_tri(double *xs, double *xb, double *vs, double *vb, + Big *big, double dt_step) +{ + double pmc0[3],pmc1[3],n0[3]; + double n1_n0[3],pmc1_pmc0[3]; + double excoll[3],eycoll[3],ezcoll[3]; + double dc1[3],dc2[3],dc3[3]; + double c1[3],c2[3],c3[3]; + double c2mc1[3],c3mc2[3],c1mc3[3]; + double pvec[3],xproduct[3]; + + // 1 and 2 = start and end of timestep + // pmc = P - C, where P = position of S, C = position of B + // n = normal to triangle + // (P-C) dot N = side of tri that S is on + // side0 = -1,0,1 for which side of tri B that S is on at start of step + // side1 = -1,0,1 for which side of tri B that S is on at end of step + + double *omega = big->omega; + double *n1 = big->norm; + + n0[0] = n1[0] - dt_step*(omega[1]*n1[2] - omega[2]*n1[1]); + n0[1] = n1[1] - dt_step*(omega[2]*n1[0] - omega[0]*n1[2]); + n0[2] = n1[2] - dt_step*(omega[0]*n1[1] - omega[1]*n1[0]); + + pmc0[0] = xs[0] - dt_step*vs[0] - xb[0] + dt_step*vb[0]; + pmc0[1] = xs[1] - dt_step*vs[1] - xb[1] + dt_step*vb[1]; + pmc0[2] = xs[2] - dt_step*vs[2] - xb[2] + dt_step*vb[2]; + pmc1[0] = xs[0] - xb[0]; + pmc1[1] = xs[1] - xb[1]; + pmc1[2] = xs[2] - xb[2]; + + double side0 = MathExtra::dot3(pmc0,n0); + double side1 = MathExtra::dot3(pmc1,n1); + + if (side0 <= 0.0 || side1 >= 0.0) return 0; + + // solve for time t (0 to 1) at which moving particle + // crosses moving/rotating tri + // quadratic equation solve of approximate parametric equation + + n1_n0[0] = n1[0]-n0[0]; + n1_n0[1] = n1[1]-n0[1]; + n1_n0[2] = n1[2]-n0[2]; + pmc1_pmc0[0] = pmc1[0]-pmc0[0]; + pmc1_pmc0[1] = pmc1[1]-pmc0[1]; + pmc1_pmc0[2] = pmc1[2]-pmc0[2]; + + double a = MathExtra::dot3(pmc1_pmc0,n1_n0); + double b = MathExtra::dot3(pmc1_pmc0,n0) + MathExtra::dot3(n1_n0,pmc0); + double c = MathExtra::dot3(pmc0,n0); + + if (a == 0.0) { + double dot0 = MathExtra::dot3(pmc0,n0); + double dot1 = MathExtra::dot3(pmc1,n0); + double root = -dot0 / (dot1 - dot0); + tfraction = root; + } else { + double term = sqrt(b*b - 4.0*a*c); + double root1 = (-b + term) / (2.0*a); + double root2 = (-b - term) / (2.0*a); + if (0.0 <= root1 && root1 <= 1.0) tfraction = root1; + else if (0.0 <= root2 && root2 <= 1.0) tfraction = root2; + else error->one(FLERR,"Bad quadratic solve for particle/tri collision"); + } + + // calculate position/orientation of S and B at collision time + // dt = time previous to now at which collision occurs + // point = S position in plane of triangle at collision time + // Excoll,Eycoll,Ezcoll = orientation of tri at collision time + // c1,c2,c3 = corner points of triangle at collision time + // nbc = normal to plane of triangle at collision time + + AtomVecTri::Bonus *tbonus; + tbonus = avec_tri->bonus; + + double *ex = big->ex; + double *ey = big->ey; + double *ez = big->ez; + int index = atom->tri[big->index]; + double *c1body = tbonus[index].c1; + double *c2body = tbonus[index].c2; + double *c3body = tbonus[index].c3; + + double dt = (1.0-tfraction)*dt_step; + + xsc[0] = xs[0] - dt*vs[0]; + xsc[1] = xs[1] - dt*vs[1]; + xsc[2] = xs[2] - dt*vs[2]; + xbc[0] = xb[0] - dt*vb[0]; + xbc[1] = xb[1] - dt*vb[1]; + xbc[2] = xb[2] - dt*vb[2]; + + excoll[0] = ex[0] - dt*(omega[1]*ex[2] - omega[2]*ex[1]); + excoll[1] = ex[1] - dt*(omega[2]*ex[0] - omega[0]*ex[2]); + excoll[2] = ex[2] - dt*(omega[0]*ex[1] - omega[1]*ex[0]); + + eycoll[0] = ey[0] - dt*(omega[1]*ey[2] - omega[2]*ey[1]); + eycoll[1] = ey[1] - dt*(omega[2]*ey[0] - omega[0]*ey[2]); + eycoll[2] = ey[2] - dt*(omega[0]*ey[1] - omega[1]*ey[0]); + + ezcoll[0] = ez[0] - dt*(omega[1]*ez[2] - omega[2]*ez[1]); + ezcoll[1] = ez[1] - dt*(omega[2]*ez[0] - omega[0]*ez[2]); + ezcoll[2] = ez[2] - dt*(omega[0]*ez[1] - omega[1]*ez[0]); + + MathExtra::matvec(excoll,eycoll,ezcoll,c1body,dc1); + MathExtra::matvec(excoll,eycoll,ezcoll,c2body,dc2); + MathExtra::matvec(excoll,eycoll,ezcoll,c3body,dc3); + + MathExtra::add3(xbc,dc1,c1); + MathExtra::add3(xbc,dc2,c2); + MathExtra::add3(xbc,dc3,c3); + + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c2,c3mc2); + MathExtra::sub3(c1,c3,c1mc3); + + MathExtra::cross3(c2mc1,c3mc2,nbc); + MathExtra::norm3(nbc); + + // check if collision pt is within triangle + // pvec = vector from tri vertex to intersection point + // xproduct = cross product of edge vec with pvec + // if dot product of xproduct with nbc < 0.0 for any of 3 edges, + // intersection point is outside tri + + MathExtra::sub3(xsc,c1,pvec); + MathExtra::cross3(c2mc1,pvec,xproduct); + if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0; + + MathExtra::sub3(xsc,c2,pvec); + MathExtra::cross3(c3mc2,pvec,xproduct); + if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0; + + MathExtra::sub3(xsc,c3,pvec); + MathExtra::cross3(c1mc3,pvec,xproduct); + if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0; + + return 1; +} + /* ---------------------------------------------------------------------- check if SRD particle S is inside wall IWALL ------------------------------------------------------------------------- */ @@ -1451,7 +1767,7 @@ double FixSRD::collision_sphere_exact(double *xs, double *xb, double vs_dot_vs,vb_dot_vb,vs_dot_vb; double vs_dot_xb,vb_dot_xs,vs_dot_xs,vb_dot_xb; double xs_dot_xs,xb_dot_xb,xs_dot_xb; - double a,b,c,scale,dt; + double a,b,c,scale; vs_dot_vs = vs[0]*vs[0] + vs[1]*vs[1] + vs[2]*vs[2]; vb_dot_vb = vb[0]*vb[0] + vb[1]*vb[1] + vb[2]*vb[2]; @@ -1470,7 +1786,7 @@ double FixSRD::collision_sphere_exact(double *xs, double *xb, b = 2.0 * (vs_dot_xb + vb_dot_xs - vs_dot_xs - vb_dot_xb); c = xs_dot_xs + xb_dot_xb - 2.0*xs_dot_xb - big->radsq; - dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a); + double dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a); xscoll[0] = xs[0] - dt*vs[0]; xscoll[1] = xs[1] - dt*vs[1]; @@ -1541,7 +1857,7 @@ double FixSRD::collision_ellipsoid_exact(double *xs, double *xb, double vs_vb[3],xs_xb[3],omega_ex[3],omega_ey[3],omega_ez[3]; double excoll[3],eycoll[3],ezcoll[3],delta[3],xbody[3],nbody[3]; double ax,bx,cx,ay,by,cy,az,bz,cz; - double a,b,c,dt,scale; + double a,b,c,scale; double *omega = big->omega; double *ex = big->ex; @@ -1551,17 +1867,9 @@ double FixSRD::collision_ellipsoid_exact(double *xs, double *xb, vs_vb[0] = vs[0]-vb[0]; vs_vb[1] = vs[1]-vb[1]; vs_vb[2] = vs[2]-vb[2]; xs_xb[0] = xs[0]-xb[0]; xs_xb[1] = xs[1]-xb[1]; xs_xb[2] = xs[2]-xb[2]; - omega_ex[0] = omega[1]*ex[2] - omega[2]*ex[1]; - omega_ex[1] = omega[2]*ex[0] - omega[0]*ex[2]; - omega_ex[2] = omega[0]*ex[1] - omega[1]*ex[0]; - - omega_ey[0] = omega[1]*ey[2] - omega[2]*ey[1]; - omega_ey[1] = omega[2]*ey[0] - omega[0]*ey[2]; - omega_ey[2] = omega[0]*ey[1] - omega[1]*ey[0]; - - omega_ez[0] = omega[1]*ez[2] - omega[2]*ez[1]; - omega_ez[1] = omega[2]*ez[0] - omega[0]*ez[2]; - omega_ez[2] = omega[0]*ez[1] - omega[1]*ez[0]; + MathExtra::cross3(omega,ex,omega_ex); + MathExtra::cross3(omega,ey,omega_ey); + MathExtra::cross3(omega,ez,omega_ez); ax = vs_vb[0]*omega_ex[0] + vs_vb[1]*omega_ex[1] + vs_vb[2]*omega_ex[2]; bx = -(vs_vb[0]*ex[0] + vs_vb[1]*ex[1] + vs_vb[2]*ex[2]); @@ -1586,7 +1894,7 @@ double FixSRD::collision_ellipsoid_exact(double *xs, double *xb, c = cx*cx*big->aradsqinv + cy*cy*big->bradsqinv + cz*cz*big->cradsqinv - 1.0; - dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a); + double dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a); xscoll[0] = xs[0] - dt*vs[0]; xscoll[1] = xs[1] - dt*vs[1]; @@ -1602,37 +1910,27 @@ double FixSRD::collision_ellipsoid_exact(double *xs, double *xb, // norm = normal in space frame // only worry about normalizing final norm vector - excoll[0] = ex[0] - dt * (omega[1]*ex[2] - omega[2]*ex[1]); - excoll[1] = ex[1] - dt * (omega[2]*ex[0] - omega[0]*ex[2]); - excoll[2] = ex[2] - dt * (omega[0]*ex[1] - omega[1]*ex[0]); - - eycoll[0] = ey[0] - dt * (omega[1]*ey[2] - omega[2]*ey[1]); - eycoll[1] = ey[1] - dt * (omega[2]*ey[0] - omega[0]*ey[2]); - eycoll[2] = ey[2] - dt * (omega[0]*ey[1] - omega[1]*ey[0]); + excoll[0] = ex[0] - dt*(omega[1]*ex[2] - omega[2]*ex[1]); + excoll[1] = ex[1] - dt*(omega[2]*ex[0] - omega[0]*ex[2]); + excoll[2] = ex[2] - dt*(omega[0]*ex[1] - omega[1]*ex[0]); - ezcoll[0] = ez[0] - dt * (omega[1]*ez[2] - omega[2]*ez[1]); - ezcoll[1] = ez[1] - dt * (omega[2]*ez[0] - omega[0]*ez[2]); - ezcoll[2] = ez[2] - dt * (omega[0]*ez[1] - omega[1]*ez[0]); + eycoll[0] = ey[0] - dt*(omega[1]*ey[2] - omega[2]*ey[1]); + eycoll[1] = ey[1] - dt*(omega[2]*ey[0] - omega[0]*ey[2]); + eycoll[2] = ey[2] - dt*(omega[0]*ey[1] - omega[1]*ey[0]); - delta[0] = xscoll[0] - xbcoll[0]; - delta[1] = xscoll[1] - xbcoll[1]; - delta[2] = xscoll[2] - xbcoll[2]; + ezcoll[0] = ez[0] - dt*(omega[1]*ez[2] - omega[2]*ez[1]); + ezcoll[1] = ez[1] - dt*(omega[2]*ez[0] - omega[0]*ez[2]); + ezcoll[2] = ez[2] - dt*(omega[0]*ez[1] - omega[1]*ez[0]); - xbody[0] = delta[0]*excoll[0] + delta[1]*excoll[1] + delta[2]*excoll[2]; - xbody[1] = delta[0]*eycoll[0] + delta[1]*eycoll[1] + delta[2]*eycoll[2]; - xbody[2] = delta[0]*ezcoll[0] + delta[1]*ezcoll[1] + delta[2]*ezcoll[2]; + MathExtra::sub3(xscoll,xbcoll,delta); + MathExtra::transpose_matvec(excoll,eycoll,ezcoll,delta,xbody); nbody[0] = xbody[0]*big->aradsqinv; nbody[1] = xbody[1]*big->bradsqinv; nbody[2] = xbody[2]*big->cradsqinv; - norm[0] = excoll[0]*nbody[0] + eycoll[0]*nbody[1] + ezcoll[0]*nbody[2]; - norm[1] = excoll[1]*nbody[0] + eycoll[1]*nbody[1] + ezcoll[1]*nbody[2]; - norm[2] = excoll[2]*nbody[0] + eycoll[2]*nbody[1] + ezcoll[2]*nbody[2]; - scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]); - norm[0] *= scale; - norm[1] *= scale; - norm[2] *= scale; + MathExtra::matvec(excoll,eycoll,ezcoll,nbody,norm); + MathExtra::norm3(norm); return dt; } @@ -1640,6 +1938,10 @@ double FixSRD::collision_ellipsoid_exact(double *xs, double *xb, /* ---------------------------------------------------------------------- collision of SRD particle S with surface of ellipsoidal big particle B inexact because just push SRD to surface of big particle at end of step + time of collision = end of step + xscoll = collision pt = position of SRD at time of collision + xbcoll = xb = position of big particle at time of collision + norm = surface normal of collision pt at time of collision ------------------------------------------------------------------------- */ void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb, @@ -1648,22 +1950,18 @@ void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb, double *norm) { double xs_xb[3],delta[3],xbody[3],nbody[3]; - double x,y,z,scale; double *ex = big->ex; double *ey = big->ey; double *ez = big->ez; - xs_xb[0] = xs[0] - xb[0]; - xs_xb[1] = xs[1] - xb[1]; - xs_xb[2] = xs[2] - xb[2]; + MathExtra::sub3(xs,xb,xs_xb); + double x = MathExtra::dot3(xs_xb,ex); + double y = MathExtra::dot3(xs_xb,ey); + double z = MathExtra::dot3(xs_xb,ez); - x = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2]; - y = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2]; - z = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2]; - - scale = 1.0/sqrt(x*x*big->aradsqinv + y*y*big->bradsqinv + - z*z*big->cradsqinv); + double scale = 1.0/sqrt(x*x*big->aradsqinv + y*y*big->bradsqinv + + z*z*big->cradsqinv); x *= scale; y *= scale; z *= scale; @@ -1681,25 +1979,73 @@ void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb, // norm = normal in space frame // only worry about normalizing final norm vector - delta[0] = xscoll[0] - xbcoll[0]; - delta[1] = xscoll[1] - xbcoll[1]; - delta[2] = xscoll[2] - xbcoll[2]; - - xbody[0] = delta[0]*ex[0] + delta[1]*ex[1] + delta[2]*ex[2]; - xbody[1] = delta[0]*ey[0] + delta[1]*ey[1] + delta[2]*ey[2]; - xbody[2] = delta[0]*ez[0] + delta[1]*ez[1] + delta[2]*ez[2]; + MathExtra::sub3(xscoll,xbcoll,delta); + MathExtra::transpose_matvec(ex,ey,ez,delta,xbody); nbody[0] = xbody[0]*big->aradsqinv; nbody[1] = xbody[1]*big->bradsqinv; nbody[2] = xbody[2]*big->cradsqinv; - norm[0] = ex[0]*nbody[0] + ey[0]*nbody[1] + ez[0]*nbody[2]; - norm[1] = ex[1]*nbody[0] + ey[1]*nbody[1] + ez[1]*nbody[2]; - norm[2] = ex[2]*nbody[0] + ey[2]*nbody[1] + ez[2]*nbody[2]; - scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]); - norm[0] *= scale; - norm[1] *= scale; - norm[2] *= scale; + MathExtra::matvec(ex,ey,ez,nbody,norm); + MathExtra::norm3(norm); +} + +/* ---------------------------------------------------------------------- + collision of SRD particle S with surface of line big particle B + exact because compute time of collision + dt = time previous to now at which collision occurs + xscoll = collision pt = position of SRD at time of collision + xbcoll = position of big particle at time of collision + norm = surface normal of collision pt at time of collision +------------------------------------------------------------------------- */ + +double FixSRD::collision_line_exact(double *xs, double *xb, + double *vs, double *vb, Big *big, + double dt_step, + double *xscoll, double *xbcoll, + double *norm) +{ + xscoll[0] = xsc[0]; + xscoll[1] = xsc[1]; + xscoll[2] = 0.0; + xbcoll[0] = xbc[0]; + xbcoll[1] = xbc[1]; + xbcoll[2] = 0.0; + + norm[0] = nbc[0]; + norm[1] = nbc[1]; + norm[2] = 0.0; + + return (1.0-tfraction)*dt_step; +} + +/* ---------------------------------------------------------------------- + collision of SRD particle S with surface of triangle big particle B + exact because compute time of collision + dt = time previous to now at which collision occurs + xscoll = collision pt = position of SRD at time of collision + xbcoll = position of big particle at time of collision + norm = surface normal of collision pt at time of collision +------------------------------------------------------------------------- */ + +double FixSRD::collision_tri_exact(double *xs, double *xb, + double *vs, double *vb, Big *big, + double dt_step, + double *xscoll, double *xbcoll, + double *norm) +{ + xscoll[0] = xsc[0]; + xscoll[1] = xsc[1]; + xscoll[2] = xsc[2]; + xbcoll[0] = xbc[0]; + xbcoll[1] = xbc[1]; + xbcoll[2] = xbc[2]; + + norm[0] = nbc[0]; + norm[1] = nbc[1]; + norm[2] = nbc[2]; + + return (1.0-tfraction)*dt_step; } /* ---------------------------------------------------------------------- @@ -1707,6 +2053,7 @@ void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb, exact because compute time of collision dt = time previous to now at which collision occurs xscoll = collision pt = position of SRD at time of collision + xbcoll = position of wall at time of collision norm = surface normal of collision pt at time of collision ------------------------------------------------------------------------- */ @@ -1737,6 +2084,7 @@ double FixSRD::collision_wall_exact(double *xs, int iwall, double *vs, inexact because just push SRD to surface of wall at end of step time of collision = end of step xscoll = collision pt = position of SRD at time of collision + xbcoll = position of wall at time of collision norm = surface normal of collision pt at time of collision ------------------------------------------------------------------------- */ @@ -1760,54 +2108,18 @@ void FixSRD::collision_wall_inexact(double *xs, int iwall, double *xscoll, } /* ---------------------------------------------------------------------- - SLIP collision with sphere - vs = velocity of SRD, vb = velocity of BIG - norm = unit normal from surface of BIG at collision pt - v of BIG particle in direction of surf normal is added to v of SRD - return vsnew of SRD -------------------------------------------------------------------------- */ - -void FixSRD::slip_sphere(double *vs, double *vb, double *norm, double *vsnew) -{ - double r1,r2,vnmag,vs_dot_n,vsurf_dot_n; - double tangent[3]; - - while (1) { - r1 = sigma * random->gaussian(); - r2 = sigma * random->gaussian(); - vnmag = sqrt(r1*r1 + r2*r2); - if (vnmag*vnmag <= vmaxsq) break; - } - - vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2]; - - tangent[0] = vs[0] - vs_dot_n*norm[0]; - tangent[1] = vs[1] - vs_dot_n*norm[1]; - tangent[2] = vs[2] - vs_dot_n*norm[2]; - - // vsurf = velocity of collision pt = translation/rotation of BIG particle - // for sphere, only vb (translation) can contribute in normal direction - - vsurf_dot_n = vb[0]*norm[0] + vb[1]*norm[1] + vb[2]*norm[2]; - - vsnew[0] = (vnmag+vsurf_dot_n)*norm[0] + tangent[0]; - vsnew[1] = (vnmag+vsurf_dot_n)*norm[1] + tangent[1]; - vsnew[2] = (vnmag+vsurf_dot_n)*norm[2] + tangent[2]; -} - -/* ---------------------------------------------------------------------- - SLIP collision with ellipsoid + SLIP collision with BIG particle with omega vs = velocity of SRD, vb = velocity of BIG xb = position of BIG, omega = rotation of BIG xsurf = collision pt on surf of BIG norm = unit normal from surface of BIG at collision pt v of BIG particle in direction of surf normal is added to v of SRD - includes component due to rotation of ellipsoid + includes component due to rotation of BIG return vsnew of SRD ------------------------------------------------------------------------- */ -void FixSRD::slip_ellipsoid(double *vs, double *vb, double *xb, Big *big, - double *xsurf, double *norm, double *vsnew) +void FixSRD::slip(double *vs, double *vb, double *xb, Big *big, + double *xsurf, double *norm, double *vsnew) { double r1,r2,vnmag,vs_dot_n,vsurf_dot_n; double tangent[3],vsurf[3]; @@ -1827,6 +2139,8 @@ void FixSRD::slip_ellipsoid(double *vs, double *vb, double *xb, Big *big, tangent[2] = vs[2] - vs_dot_n*norm[2]; // vsurf = velocity of collision pt = translation/rotation of BIG particle + // NOTE: for sphere could just use vsurf = vb, since w x (xsurf-xb) + // is orthogonal to norm and thus doesn't contribute to vsurf_dot_n vsurf[0] = vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]); vsurf[1] = vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]); @@ -1887,7 +2201,7 @@ void FixSRD::slip_wall(double *vs, int iwall, double *norm, double *vsnew) } /* ---------------------------------------------------------------------- - NO-SLIP collision with sphere or ellipsoid + NO-SLIP collision with BIG particle including WALL vs = velocity of SRD, vb = velocity of BIG xb = position of BIG, omega = rotation of BIG xsurf = collision pt on surf of BIG @@ -1897,12 +2211,11 @@ void FixSRD::slip_wall(double *vs, int iwall, double *norm, double *vsnew) return vsnew of SRD ------------------------------------------------------------------------- */ -void FixSRD::noslip(double *vs, double *vb, double *xb, Big *big, +void FixSRD::noslip(double *vs, double *vb, double *xb, Big *big, int iwall, double *xsurf, double *norm, double *vsnew) { double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2; double tangent1[3],tangent2[3]; - double *omega = big->omega; vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2]; @@ -1932,60 +2245,20 @@ void FixSRD::noslip(double *vs, double *vb, double *xb, Big *big, vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1]; vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2]; - // add in velocity of collision pt = translation/rotation of BIG particle + // add in velocity of collision pt + // for WALL: velocity of wall in one dim + // else: translation/rotation of BIG particle - vsnew[0] += vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]); - vsnew[1] += vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]); - vsnew[2] += vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]); -} + if (big->type == WALL) { + int dim = wallwhich[iwall] / 2; + vsnew[dim] += vwall[iwall]; -/* ---------------------------------------------------------------------- - NO-SLIP collision with wall IWALL - vs = velocity of SRD - xsurf = collision pt on surf of WALL - norm = unit normal from WALL at collision pt - v of collision pt is added to v of SRD - return vsnew of SRD -------------------------------------------------------------------------- */ - -void FixSRD::noslip_wall(double *vs, int iwall, - double *xsurf, double *norm, double *vsnew) -{ - double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2; - double tangent1[3],tangent2[3]; - - vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2]; - - tangent1[0] = vs[0] - vs_dot_n*norm[0]; - tangent1[1] = vs[1] - vs_dot_n*norm[1]; - tangent1[2] = vs[2] - vs_dot_n*norm[2]; - scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] + - tangent1[2]*tangent1[2]); - tangent1[0] *= scale; - tangent1[1] *= scale; - tangent1[2] *= scale; - - tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1]; - tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2]; - tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0]; - - while (1) { - r1 = sigma * random->gaussian(); - r2 = sigma * random->gaussian(); - vnmag = sqrt(r1*r1 + r2*r2); - vtmag1 = sigma * random->gaussian(); - vtmag2 = sigma * random->gaussian(); - if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break; + } else { + double *omega = big->omega; + vsnew[0] += vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]); + vsnew[1] += vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]); + vsnew[2] += vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]); } - - vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0]; - vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1]; - vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2]; - - // add in velocity of collision pt = velocity of wall - - int dim = wallwhich[iwall] / 2; - vsnew[dim] += vwall[iwall]; } /* ---------------------------------------------------------------------- @@ -2027,6 +2300,7 @@ void FixSRD::force_torque(double *vsold, double *vsnew, ------------------------------------------------------------------------- */ void FixSRD::force_wall(double *vsold, double *vsnew, int iwall) + { double dpdt[3]; @@ -2100,12 +2374,20 @@ void FixSRD::parameterize() AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double *radius = atom->radius; int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; int *mask = atom->mask; int nlocal = atom->nlocal; - any_ellipsoids = 0; + int any_ellipsoids = 0; + int any_lines = 0; + int any_tris = 0; maxbigdiam = 0.0; minbigdiam = BIG; @@ -2123,6 +2405,20 @@ void FixSRD::parameterize() minbigdiam = MIN(minbigdiam,2.0*shape[0]); minbigdiam = MIN(minbigdiam,2.0*shape[1]); minbigdiam = MIN(minbigdiam,2.0*shape[2]); + } else if (line && line[i] >= 0) { + any_lines = 1; + double length = lbonus[line[i]].length; + maxbigdiam = MAX(maxbigdiam,length); + minbigdiam = MIN(minbigdiam,length); + } else if (tri && tri[i] >= 0) { + any_tris = 1; + double length1 = MathExtra::len3(tbonus[tri[i]].c1); + double length2 = MathExtra::len3(tbonus[tri[i]].c2); + double length3 = MathExtra::len3(tbonus[tri[i]].c3); + double length = MAX(length1,length2); + length = MAX(length,length3); + maxbigdiam = MAX(maxbigdiam,length); + minbigdiam = MIN(minbigdiam,length); } else error->one(FLERR,"Big particle in fix srd cannot be point particle"); } @@ -2137,10 +2433,20 @@ void FixSRD::parameterize() int itmp = any_ellipsoids; MPI_Allreduce(&itmp,&any_ellipsoids,1,MPI_INT,MPI_MAX,world); + itmp = any_lines; + MPI_Allreduce(&itmp,&any_lines,1,MPI_INT,MPI_MAX,world); + itmp = any_tris; + MPI_Allreduce(&itmp,&any_tris,1,MPI_INT,MPI_MAX,world); + + if (any_lines && overlap == 0) + error->all(FLERR,"Cannot use lines with fix srd unless overlap is set"); + if (any_tris && overlap == 0) + error->all(FLERR,"Cannot use tris with fix srd unless overlap is set"); - // big particles are only torqued if are ellipsoids or NOSLIP collisions + // big particles are only torqued if ellipsoids/lines/tris or NOSLIP - if (any_ellipsoids == 0 && collidestyle == SLIP) torqueflag = 0; + if (any_ellipsoids == 0 && any_lines == 0 && any_tris == 0 && + collidestyle == SLIP) torqueflag = 0; else torqueflag = 1; // mass of SRD particles, require monodispersity @@ -2186,28 +2492,46 @@ void FixSRD::parameterize() vmaxsq = vmax*vmax; // volbig = total volume of all big particles + // LINE/TRI particles have no volume + // incorrect if part of rigid particles, so add fudge factor with WIDTH // apply radfactor to reduce final volume double volbig = 0.0; + double WIDTH = 1.0; if (dimension == 3) { for (int i = 0; i < nlocal; i++) if (mask[i] & biggroupbit) { - if (radius && radius[i] > 0.0) - volbig += 4.0/3.0*MY_PI*radius[i]*radius[i]*radius[i]; - else if (ellipsoid && ellipsoid[i] >= 0) { + if (radius && radius[i] > 0.0) { + double r = radfactor * radius[i]; + volbig += 4.0/3.0*MY_PI * r*r*r;; + } else if (ellipsoid && ellipsoid[i] >= 0) { double *shape = ebonus[ellipsoid[i]].shape; - volbig += 4.0/3.0*MY_PI * shape[0]*shape[1]*shape[2]; + volbig += 4.0/3.0*MY_PI * shape[0]*shape[1]*shape[2] * + radfactor*radfactor*radfactor; + } else if (tri && tri[i] >= 0) { + double *c1 = tbonus[tri[i]].c1; + double *c2 = tbonus[tri[i]].c2; + double *c3 = tbonus[tri[i]].c3; + double c2mc1[3],c3mc1[3],cross[3]; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + MathExtra::cross3(c2mc1,c3mc1,cross); + volbig += 0.5 * MathExtra::len3(cross); } } } else { for (int i = 0; i < nlocal; i++) if (mask[i] & biggroupbit) { - if (radius && radius[i] > 0.0) - volbig += MY_PI*radius[i]*radius[i]; - else if (ellipsoid && ellipsoid[i] >= 0) { + if (radius && radius[i] > 0.0) { + double r = radfactor * radius[i]; + volbig += MY_PI * r*r; + } else if (ellipsoid && ellipsoid[i] >= 0) { double *shape = ebonus[ellipsoid[i]].shape; - volbig += MY_PI*shape[0]*shape[1]; + volbig += MY_PI * shape[0]*shape[1] * radfactor*radfactor; + } else if (line && line[i] >= 0) { + double length = lbonus[line[i]].length; + volbig += length * WIDTH; } } } @@ -2215,9 +2539,6 @@ void FixSRD::parameterize() tmp = volbig; MPI_Allreduce(&tmp,&volbig,1,MPI_DOUBLE,MPI_SUM,world); - if (dimension == 3) volbig *= radfactor*radfactor*radfactor; - else volbig *= radfactor*radfactor; - // particle counts bigint mbig = 0; @@ -2228,7 +2549,10 @@ void FixSRD::parameterize() mass_big = 0.0; for (int i = 0; i < nlocal; i++) - if (mask[i] & biggroupbit) mass_big += rmass[i]; + if (mask[i] & biggroupbit) { + if (rmass) mass_big += rmass[i]; + else mass_big += mass[type[i]]; + } tmp = mass_big; MPI_Allreduce(&tmp,&mass_big,1,MPI_DOUBLE,MPI_SUM,world); @@ -2369,7 +2693,8 @@ void FixSRD::parameterize() if (cubicflag == CUBIC_ERROR) error->all(FLERR,"SRD bin size for fix srd differs from user request"); if (me == 0) - error->warning(FLERR,"SRD bin size for fix srd differs from user request"); + error->warning(FLERR, + "SRD bin size for fix srd differs from user request"); } // error if lamda < 0.6 of SRD grid size and no shifting allowed @@ -2400,30 +2725,46 @@ void FixSRD::parameterize() /* ---------------------------------------------------------------------- set static parameters of each big particle, owned and ghost called each reneighboring - use radfactor in distance parameters + use radfactor in distance parameters as appropriate ------------------------------------------------------------------------- */ void FixSRD::big_static() { int i; - double rad,arad,brad,crad; - double *shape; + double rad,arad,brad,crad,length,length1,length2,length3; + double *shape,*c1,*c2,*c3; + double c2mc1[3],c3mc1[3]; AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double *radius = atom->radius; int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; + int *type = atom->type; double skinhalf = 0.5 * neighbor->skin; for (int k = 0; k < nbig; k++) { i = biglist[k].index; + + // sphere + // set radius and radsq and cutoff based on radius + if (radius && radius[i] > 0.0) { biglist[k].type = SPHERE; rad = radfactor*radius[i]; biglist[k].radius = rad; biglist[k].radsq = rad*rad; biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf); + + // ellipsoid + // set abc radsqinv and cutoff based on max radius + } else if (ellipsoid && ellipsoid[i] >= 0) { shape = ebonus[ellipsoid[i]].shape; biglist[k].type = ELLIPSOID; @@ -2436,33 +2777,67 @@ void FixSRD::big_static() rad = MAX(arad,brad); rad = MAX(rad,crad); biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf); + + // line + // set length and cutoff based on 1/2 length + + } else if (line && line[i] >= 0) { + length = lbonus[line[i]].length; + biglist[k].type = LINE; + biglist[k].length = length; + rad = 0.5*length; + biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf); + + // tri + // set normbody based on c1,c2,c3 + // set cutoff based on point furthest from centroid + + } else if (tri && tri[i] >= 0) { + biglist[k].type = TRIANGLE; + c1 = tbonus[tri[i]].c1; + c2 = tbonus[tri[i]].c2; + c3 = tbonus[tri[i]].c3; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + MathExtra::cross3(c2mc1,c3mc1,biglist[k].normbody); + length1 = MathExtra::len3(c1); + length2 = MathExtra::len3(c2); + length3 = MathExtra::len3(c3); + rad = MAX(length1,length2); + rad = MAX(rad,length3); + biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf); } } } /* ---------------------------------------------------------------------- - set dynamics parameters of each big particle, owned and ghost - for ELLIPSOID, need current omega and ex,ey,ez - for SPHERE, need current omega from atom->omega or atom->angmom + set dynamic parameters of each big particle, owned and ghost called each timestep ------------------------------------------------------------------------- */ void FixSRD::big_dynamic() { int i; - double *shape,*quat; + double *shape,*quat,*inertia; + double inertiaone[3]; AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double **omega = atom->omega; double **angmom = atom->angmom; double *rmass = atom->rmass; int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; for (int k = 0; k < nbig; k++) { i = biglist[k].index; - // sphere with omega + // sphere // set omega from atom->omega directly if (biglist[k].type == SPHERE) { @@ -2470,15 +2845,45 @@ void FixSRD::big_dynamic() biglist[k].omega[1] = omega[i][1]; biglist[k].omega[2] = omega[i][2]; - // ellipsoid with angmom - // calculate ex,ey,ez and omega from quaternion and angmom + // ellipsoid + // set ex,ey,ez from quaternion + // set omega from angmom & ex,ey,ez } else if (biglist[k].type == ELLIPSOID) { - shape = ebonus[ellipsoid[i]].shape; quat = ebonus[ellipsoid[i]].quat; - exyz_from_q(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez); - omega_from_mq(angmom[i],biglist[k].ex,biglist[k].ey,biglist[k].ez, - rmass[i],shape,biglist[k].omega); + MathExtra::q_to_exyz(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez); + shape = ebonus[ellipsoid[i]].shape; + inertiaone[0] = EINERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]); + inertiaone[1] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]); + inertiaone[2] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]); + MathExtra::angmom_to_omega(angmom[i], + biglist[k].ex,biglist[k].ey,biglist[k].ez, + inertiaone,biglist[k].omega); + + // line + // set omega from atom->omega directly + + } else if (biglist[k].type == LINE) { + biglist[k].theta = lbonus[line[i]].theta; + biglist[k].omega[0] = omega[i][0]; + biglist[k].omega[1] = omega[i][1]; + biglist[k].omega[2] = omega[i][2]; + + // tri + // set ex,ey,ez from quaternion + // set omega from angmom & ex,ey,ez + // set unit space-frame norm from body-frame norm + + } else if (biglist[k].type == TRIANGLE) { + quat = tbonus[tri[i]].quat; + MathExtra::q_to_exyz(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez); + inertia = tbonus[tri[i]].inertia; + MathExtra::angmom_to_omega(angmom[i], + biglist[k].ex,biglist[k].ey,biglist[k].ez, + inertia,biglist[k].omega); + MathExtra::matvec(biglist[k].ex,biglist[k].ey,biglist[k].ez, + biglist[k].normbody,biglist[k].norm); + MathExtra::norm3(biglist[k].norm); } } } @@ -2967,10 +3372,10 @@ void FixSRD::setup_velocity_shift(int ishift, int dynamic) for (m = 0; m < nsend; m++) vbin[sendlist[m]].owner = 0; } - // if triclinic and streamflag: - // set xctr (in lamda units) for all nbins so can compute bin vstream + // if tstat and deformflag: + // set xctr for all nbins in lamda units so can later compute vstream of bin - if (triclinic && streamflag) { + if (tstat && deformflag) { m = 0; for (k = 0; k < nbinz; k++) for (j = 0; j < nbiny; j++) @@ -3182,55 +3587,6 @@ double FixSRD::bin_bin_distance(int i, int j, int k) return (delx*delx + dely*dely + delz*delz); } -/* ---------------------------------------------------------------------- - compute space-frame ex,ey,ez from current quaternion q - ex,ey,ez = space-frame coords of 1st,2nd,3rd principal axis - operation is ex = q' d q = Q d, where d is (1,0,0) = 1st axis in body frame -------------------------------------------------------------------------- */ - -void FixSRD::exyz_from_q(double *q, double *ex, double *ey, double *ez) -{ - ex[0] = q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3]; - ex[1] = 2.0 * (q[1]*q[2] + q[0]*q[3]); - ex[2] = 2.0 * (q[1]*q[3] - q[0]*q[2]); - - ey[0] = 2.0 * (q[1]*q[2] - q[0]*q[3]); - ey[1] = q[0]*q[0] - q[1]*q[1] + q[2]*q[2] - q[3]*q[3]; - ey[2] = 2.0 * (q[2]*q[3] + q[0]*q[1]); - - ez[0] = 2.0 * (q[1]*q[3] + q[0]*q[2]); - ez[1] = 2.0 * (q[2]*q[3] - q[0]*q[1]); - ez[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; -} - -/* ---------------------------------------------------------------------- - compute omega from angular momentum - w = omega = angular velocity in space frame - wbody = angular velocity in body frame - set wbody component to 0.0 if inertia component is 0.0 - otherwise body can spin easily around that axis - project space-frame angular momentum onto body axes - and divide by principal moments -------------------------------------------------------------------------- */ - -void FixSRD::omega_from_mq(double *m, double *ex, double *ey, double *ez, - double mass, double *shape, double *w) -{ - double inertia[3],wbody[3]; - - inertia[0] = 0.2*mass * (shape[1]*shape[1]+shape[2]*shape[2]); - inertia[1] = 0.2*mass * (shape[0]*shape[0]+shape[2]*shape[2]); - inertia[2] = 0.2*mass * (shape[0]*shape[0]+shape[1]*shape[1]); - - wbody[0] = (m[0]*ex[0] + m[1]*ex[1] + m[2]*ex[2]) / inertia[0]; - wbody[1] = (m[0]*ey[0] + m[1]*ey[1] + m[2]*ey[2]) / inertia[1]; - wbody[2] = (m[0]*ez[0] + m[1]*ez[1] + m[2]*ez[2]) / inertia[2]; - - w[0] = wbody[0]*ex[0] + wbody[1]*ey[0] + wbody[2]*ez[0]; - w[1] = wbody[0]*ex[1] + wbody[1]*ey[1] + wbody[2]*ez[1]; - w[2] = wbody[0]*ex[2] + wbody[1]*ey[2] + wbody[2]*ez[2]; -} - /* ---------------------------------------------------------------------- */ int FixSRD::pack_reverse_comm(int n, int first, double *buf) @@ -3365,6 +3721,90 @@ void FixSRD::velocity_stats(int groupnum) /* ---------------------------------------------------------------------- */ +double FixSRD::newton_raphson(double t1, double t2) +{ + double f1,f2,df,tlo,thi; + lineside(t1,f1,df); + if (f1 < 0.0) { + tlo = t1; + thi = t2; + } else { + thi = t1; + tlo = t2; + } + + double f; + double t = 0.5*(t1+t2); + double dtold = fabs(t2-t1); + double dt = dtold; + lineside(t,f,df); + + double temp; + for (int i = 0; i < MAXITER; i++) { + if ((((t-thi)*df - f)*((t-tlo)*df - f) > 0.0) || + (fabs(2.0*f) > fabs(dtold*df))) { + dtold = dt; + dt = 0.5 * (thi-tlo); + t = tlo + dt; + if (tlo == t) return t; + } else { + dtold = dt; + dt = f / df; + temp = t; + t -= dt; + if (temp == t) return t; + } + if (fabs(dt) < TOLERANCE) return t; + lineside(t,f,df); + if (f < 0.0) tlo = t; + else thi = t; + } + + return t; +} + +/* ---------------------------------------------------------------------- */ + +void FixSRD::lineside(double t, double &f, double &df) +{ + double p[2],c[2]; + + p[0] = xs0[0] + (xs1[0]-xs0[0])*t; + p[1] = xs0[1] + (xs1[1]-xs0[1])*t; + c[0] = xb0[0] + (xb1[0]-xb0[0])*t; + c[1] = xb0[1] + (xb1[1]-xb0[1])*t; + double dtheta = theta1 - theta0; + double theta = theta0 + dtheta*t; + double cosT = cos(theta); + double sinT = sin(theta); + + f = (p[1]-c[1]) * cosT - (p[0]-c[0]) * sinT; + df = ((xs1[1]-xs0[1]) - (xb1[1]-xb0[1]))*cosT - (p[1]-c[1])*sinT*dtheta - + ((xs1[0]-xs0[0]) - (xb1[0]-xb0[0]))*sinT - (p[0]-c[0])*cosT*dtheta; +} + +/* ---------------------------------------------------------------------- */ + +void FixSRD::triside(double t, double &f, double &df) +{ + double p[2],c[2]; + + p[0] = xs0[0] + (xs1[0]-xs0[0])*t; + p[1] = xs0[1] + (xs1[1]-xs0[1])*t; + c[0] = xb0[0] + (xb1[0]-xb0[0])*t; + c[1] = xb0[1] + (xb1[1]-xb0[1])*t; + double dtheta = theta1 - theta0; + double theta = theta0 + dtheta*t; + double cosT = cos(theta); + double sinT = sin(theta); + + f = (p[1]-c[1]) * cosT - (p[0]-c[0]) * sinT; + df = ((xs1[1]-xs0[1]) - (xb1[1]-xb0[1]))*cosT - (p[1]-c[1])*sinT*dtheta - + ((xs1[0]-xs0[0]) - (xb1[0]-xb0[0]))*sinT - (p[0]-c[0])*cosT*dtheta; +} + +/* ---------------------------------------------------------------------- */ + double FixSRD::memory_usage() { double bytes = 0.0; diff --git a/src/SRD/fix_srd.h b/src/SRD/fix_srd.h index 8552078e6d..43d9f7c2e3 100644 --- a/src/SRD/fix_srd.h +++ b/src/SRD/fix_srd.h @@ -43,9 +43,9 @@ class FixSRD : public Fix { int me,nprocs; int bigexist,biggroup,biggroupbit; int collidestyle,lamdaflag,overlap,insideflag,exactflag,maxbounceallow; - int cubicflag,shiftuser,shiftseed,shiftflag,streamflag; + int cubicflag,shiftuser,shiftseed,shiftflag,tstat; double gridsrd,gridsearch,lamda,radfactor,cubictol; - int triclinic,change_size,change_shape; + int triclinic,change_size,change_shape,deformflag; double dt_big,dt_srd; double mass_big,mass_srd; @@ -64,6 +64,8 @@ class FixSRD : public Fix { double walltrigger; class AtomVecEllipsoid *avec_ellipsoid; + class AtomVecLine *avec_line; + class AtomVecTri *avec_tri; // for orthogonal box, these are in box units // for triclinic box, these are in lamda units @@ -92,18 +94,21 @@ class FixSRD : public Fix { struct Big { int index; // local index of particle/wall - int type; // SPHERE or ELLIPSOID or WALL + int type; // SPHERE or ELLIPSOID or LINE or TRI or WALL double radius,radsq; // radius of sphere double aradsqinv; // 3 ellipsoid radii double bradsqinv; double cradsqinv; + double length; // length of line segment + double normbody[3]; // normal of tri in body-frame double cutbinsq; // add big to bin if within this distance - double omega[3]; // current omega for sphere or ellipsoid - double ex[3],ey[3],ez[3]; // current orientation vecs for ellipsoid + double omega[3]; // current omega for sphere/ellipsoid/tri/line + double ex[3],ey[3],ez[3]; // current orientation vecs for ellipsoid/tri + double norm[3]; // current unit normal of tri in space-frame + double theta; // current orientation of line }; Big *biglist; // list of info for each owned & ghost big and wall - int any_ellipsoids; // 1 if any big particles are ellipsoids int torqueflag; // 1 if any big particle is torqued // current size of particle-based arrays @@ -123,7 +128,7 @@ class FixSRD : public Fix { int owner; // 1 if I am owner of this bin, 0 if not int n; // # of SRD particles in bin double xctr[3]; // center point of bin, only used for triclinic - double vave[3]; // sum of v components for SRD particles in bin + double vsum[3]; // sum of v components for SRD particles in bin double random; // random value if I am owner }; @@ -167,6 +172,17 @@ class FixSRD : public Fix { int maxstencil; // max # of bins stencil array can hold int **stencil; // list of 3d bin offsets a big particle can overlap + // persistent data for line/tri collision calculations + + double tfraction,theta0,theta1; + double xs0[3],xs1[3],xsc[3]; + double xb0[3],xb1[3],xbc[3]; + double nbc[3]; + + // shared data for triangle collision calculations + + // private functions + void reset_velocities(); void vbin_comm(int); void vbin_pack(BinAve *, int, int *, double *); @@ -177,6 +193,8 @@ class FixSRD : public Fix { int inside_sphere(double *, double *, Big *); int inside_ellipsoid(double *, double *, Big *); + int inside_line(double *, double *, double *, double *, Big *, double); + int inside_tri(double *, double *, double *, double *, Big *, double); int inside_wall(double *, int); double collision_sphere_exact(double *, double *, double *, double *, @@ -187,18 +205,19 @@ class FixSRD : public Fix { Big *, double *, double *, double *); void collision_ellipsoid_inexact(double *, double *, Big *, double *, double *, double *); + double collision_line_exact(double *, double *, double *, double *, + Big *, double, double *, double *, double *); + double collision_tri_exact(double *, double *, double *, double *, + Big *, double, double *, double *, double *); double collision_wall_exact(double *, int, double *, double *, double *, double *); void collision_wall_inexact(double *, int, double *, double *, double *); - void slip_sphere(double *, double *, double *, double *); - void slip_ellipsoid(double *, double *, double *, Big *, - double *, double *, double *); + void slip(double *, double *, double *, Big *, + double *, double *, double *); void slip_wall(double *, int, double *, double *); - - void noslip(double *, double *, double *, Big *, + void noslip(double *, double *, double *, Big *, int, double *, double *, double *); - void noslip_wall(double *, int, double *, double *, double *); void force_torque(double *, double *, double *, double *, double *, double *); @@ -217,11 +236,12 @@ class FixSRD : public Fix { double point_bin_distance(double *, int, int, int); double bin_bin_distance(int, int, int); - void exyz_from_q(double *, double *, double *, double *); - void omega_from_mq(double *, double *, double *, double *, - double, double *, double *); void velocity_stats(int); + double newton_raphson(double, double); + void lineside(double, double &, double &); + void triside(double, double &, double &); + double distance(int, int); void print_collision(int, int, int, double, double, double *, double *, double *, int); diff --git a/src/atom.cpp b/src/atom.cpp index f42b1250f1..023d7a173f 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -75,7 +75,7 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp) radius = rmass = NULL; vfrac = s0 = NULL; x0 = NULL; - ellipsoid = NULL; + ellipsoid = line = tri = NULL; spin = NULL; eradius = ervel = erforce = NULL; cs = csforce = vforce = ervelforce = NULL; @@ -106,7 +106,8 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp) // initialize atom style and array existence flags // customize by adding new flag - sphere_flag = ellipsoid_flag = peri_flag = electron_flag = 0; + sphere_flag = ellipsoid_flag = line_flag = tri_flag = 0; + peri_flag = electron_flag = 0; wavepacket_flag = sph_flag = 0; molecule_flag = q_flag = mu_flag = 0; @@ -185,6 +186,8 @@ Atom::~Atom() memory->destroy(s0); memory->destroy(x0); memory->destroy(ellipsoid); + memory->destroy(line); + memory->destroy(tri); memory->destroy(spin); memory->destroy(eradius); memory->destroy(ervel); @@ -259,8 +262,9 @@ void Atom::create_avec(const char *style, int narg, char **arg, char *suffix) // may have been set by old avec // customize by adding new flag - sphere_flag = ellipsoid_flag = peri_flag = electron_flag = 0; - + sphere_flag = ellipsoid_flag = line_flag = tri_flag = 0; + peri_flag = electron_flag = 0; + molecule_flag = q_flag = mu_flag = 0; rmass_flag = radius_flag = omega_flag = torque_flag = angmom_flag = 0; vfrac_flag = spin_flag = eradius_flag = ervel_flag = erforce_flag = 0; diff --git a/src/atom.h b/src/atom.h index 98b687ec9a..429aacb1c2 100644 --- a/src/atom.h +++ b/src/atom.h @@ -51,7 +51,7 @@ class Atom : protected Pointers { double **omega,**angmom,**torque; double *radius,*rmass,*vfrac,*s0; double **x0; - int *ellipsoid; + int *ellipsoid,*line,*tri; int *spin; double *eradius,*ervel,*erforce,*ervelforce; double *cs,*csforce,*vforce; @@ -84,7 +84,7 @@ class Atom : protected Pointers { // atom style and per-atom array existence flags // customize by adding new flag - int sphere_flag,ellipsoid_flag,peri_flag,electron_flag; + int sphere_flag,ellipsoid_flag,line_flag,tri_flag,peri_flag,electron_flag; int wavepacket_flag,sph_flag; int molecule_flag,q_flag,mu_flag; diff --git a/src/compute_property_atom.cpp b/src/compute_property_atom.cpp index f7605d5552..80efd8a5bf 100644 --- a/src/compute_property_atom.cpp +++ b/src/compute_property_atom.cpp @@ -11,10 +11,14 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ +#include "math.h" #include "string.h" #include "compute_property_atom.h" +#include "math_extra.h" #include "atom.h" #include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" #include "update.h" #include "domain.h" #include "memory.h" @@ -173,39 +177,39 @@ ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) : pack_choice[i] = &ComputePropertyAtom::pack_angmomz; } else if (strcmp(arg[iarg],"shapex") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_shapex; } else if (strcmp(arg[iarg],"shapey") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_shapey; } else if (strcmp(arg[iarg],"shapez") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_shapez; } else if (strcmp(arg[iarg],"quatw") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_quatw; } else if (strcmp(arg[iarg],"quati") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_quati; } else if (strcmp(arg[iarg],"quatj") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_quatj; } else if (strcmp(arg[iarg],"quatk") == 0) { - avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - if (!avec) error->all(FLERR,"Compute property/atom for " - "atom property that isn't allocated"); + avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + if (!avec_ellipsoid) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_quatk; } else if (strcmp(arg[iarg],"tqx") == 0) { if (!atom->torque_flag) @@ -244,6 +248,83 @@ ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) : "atom property that isn't allocated"); pack_choice[i] = &ComputePropertyAtom::pack_erforce; + } else if (strcmp(arg[iarg],"end1x") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end1x; + } else if (strcmp(arg[iarg],"end1y") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end1y; + } else if (strcmp(arg[iarg],"end1z") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end1z; + } else if (strcmp(arg[iarg],"end2x") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end2x; + } else if (strcmp(arg[iarg],"end2y") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end2y; + } else if (strcmp(arg[iarg],"end2z") == 0) { + avec_line = (AtomVecLine *) atom->style_match("line"); + if (!avec_line) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_end2z; + + } else if (strcmp(arg[iarg],"corner1x") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner1x; + } else if (strcmp(arg[iarg],"corner1y") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner1y; + } else if (strcmp(arg[iarg],"corner1z") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner1z; + } else if (strcmp(arg[iarg],"corner2x") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner2x; + } else if (strcmp(arg[iarg],"corner2y") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner2y; + } else if (strcmp(arg[iarg],"corner2z") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner2z; + } else if (strcmp(arg[iarg],"corner3x") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner3x; + } else if (strcmp(arg[iarg],"corner3y") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner3y; + } else if (strcmp(arg[iarg],"corner3z") == 0) { + avec_tri = (AtomVecTri *) atom->style_match("tri"); + if (!avec_tri) error->all(FLERR,"Compute property/atom for " + "atom property that isn't allocated"); + pack_choice[i] = &ComputePropertyAtom::pack_corner3z; + } else error->all(FLERR,"Invalid keyword in compute property/atom command"); } @@ -994,7 +1075,7 @@ void ComputePropertyAtom::pack_angmomz(int n) void ComputePropertyAtom::pack_shapex(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1011,7 +1092,7 @@ void ComputePropertyAtom::pack_shapex(int n) void ComputePropertyAtom::pack_shapey(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1028,7 +1109,7 @@ void ComputePropertyAtom::pack_shapey(int n) void ComputePropertyAtom::pack_shapez(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1045,7 +1126,7 @@ void ComputePropertyAtom::pack_shapez(int n) void ComputePropertyAtom::pack_quatw(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1062,7 +1143,7 @@ void ComputePropertyAtom::pack_quatw(int n) void ComputePropertyAtom::pack_quati(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1079,7 +1160,7 @@ void ComputePropertyAtom::pack_quati(int n) void ComputePropertyAtom::pack_quatj(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1096,7 +1177,7 @@ void ComputePropertyAtom::pack_quatj(int n) void ComputePropertyAtom::pack_quatk(int n) { - AtomVecEllipsoid::Bonus *bonus = avec->bonus; + AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; int *mask = atom->mask; int nlocal = atom->nlocal; @@ -1213,3 +1294,294 @@ void ComputePropertyAtom::pack_erforce(int n) n += nvalues; } } + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end1x(int n) +{ + AtomVecLine::Bonus *bonus = avec_line->bonus; + int *line = atom->line; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && line[i] >= 0) + buf[n] = x[i][0] - 0.5*bonus[line[i]].length*cos(bonus[line[i]].theta); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end1y(int n) +{ + AtomVecLine::Bonus *bonus = avec_line->bonus; + int *line = atom->line; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && line[i] >= 0) + buf[n] = x[i][1] - 0.5*bonus[line[i]].length*sin(bonus[line[i]].theta); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end1z(int n) +{ + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = x[i][2]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end2x(int n) +{ + AtomVecLine::Bonus *bonus = avec_line->bonus; + int *line = atom->line; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && line[i] >= 0) + buf[n] = x[i][0] + 0.5*bonus[line[i]].length*cos(bonus[line[i]].theta); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end2y(int n) +{ + AtomVecLine::Bonus *bonus = avec_line->bonus; + int *line = atom->line; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && line[i] >= 0) + buf[n] = x[i][1] + 0.5*bonus[line[i]].length*sin(bonus[line[i]].theta); + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_end2z(int n) +{ + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) buf[n] = x[i][2]; + else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner1x(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c1,c); + buf[n] = x[i][0] + c[0]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner1y(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c1,c); + buf[n] = x[i][1] + c[1]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner1z(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c1,c); + buf[n] = x[i][2] + c[2]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner2x(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c2,c); + buf[n] = x[i][0] + c[0]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner2y(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c2,c); + buf[n] = x[i][1] + c[1]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner2z(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c2,c); + buf[n] = x[i][2] + c[2]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner3x(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c3,c); + buf[n] = x[i][0] + c[0]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner3y(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c3,c); + buf[n] = x[i][1] + c[1]; + } else buf[n] = 0.0; + n += nvalues; + } +} + +/* ---------------------------------------------------------------------- */ + +void ComputePropertyAtom::pack_corner3z(int n) +{ + AtomVecTri::Bonus *bonus = avec_tri->bonus; + int *tri = atom->tri; + double **x = atom->x; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + double p[3][3],c[3]; + for (int i = 0; i < nlocal; i++) { + if ((mask[i] & groupbit) && tri[i] >= 0) { + MathExtra::quat_to_mat(bonus[tri[i]].quat,p); + MathExtra::matvec(p,bonus[tri[i]].c3,c); + buf[n] = x[i][2] + c[2]; + } else buf[n] = 0.0; + n += nvalues; + } +} diff --git a/src/compute_property_atom.h b/src/compute_property_atom.h index b32d0a93df..8f675b6204 100644 --- a/src/compute_property_atom.h +++ b/src/compute_property_atom.h @@ -38,7 +38,9 @@ class ComputePropertyAtom : public Compute { double *vector; double **array; double *buf; - class AtomVecEllipsoid *avec; + class AtomVecEllipsoid *avec_ellipsoid; + class AtomVecLine *avec_line; + class AtomVecTri *avec_tri; typedef void (ComputePropertyAtom::*FnPtrPack)(int); FnPtrPack *pack_choice; // ptrs to pack functions @@ -101,6 +103,21 @@ class ComputePropertyAtom : public Compute { void pack_eradius(int); void pack_ervel(int); void pack_erforce(int); + void pack_end1x(int); + void pack_end1y(int); + void pack_end1z(int); + void pack_end2x(int); + void pack_end2y(int); + void pack_end2z(int); + void pack_corner1x(int); + void pack_corner1y(int); + void pack_corner1z(int); + void pack_corner2x(int); + void pack_corner2y(int); + void pack_corner2z(int); + void pack_corner3x(int); + void pack_corner3y(int); + void pack_corner3z(int); }; } diff --git a/src/fix_rigid.cpp b/src/fix_rigid.cpp index cf63dfa116..63df87b782 100644 --- a/src/fix_rigid.cpp +++ b/src/fix_rigid.cpp @@ -19,6 +19,8 @@ #include "math_extra.h" #include "atom.h" #include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" #include "domain.h" #include "update.h" #include "respa.h" @@ -28,14 +30,20 @@ #include "random_mars.h" #include "force.h" #include "output.h" +#include "math_const.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; +using namespace MathConst; #define TOLERANCE 1.0e-6 #define EPSILON 1.0e-7 +#define SINERTIA 0.4 // moment of inertia prefactor for sphere +#define EINERTIA 0.4 // moment of inertia prefactor for ellipsoid +#define LINERTIA (1.0/12.0) // moment of inertia prefactor for line segment + /* ---------------------------------------------------------------------- */ FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) : @@ -56,12 +64,12 @@ FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) : // perform initial allocation of atom-based arrays // register with Atom class - extended = dorientflag = qorientflag = 0; + extended = orientflag = dorientflag = 0; body = NULL; displace = NULL; eflags = NULL; + orient = NULL; dorient = NULL; - qorient = NULL; grow_arrays(atom->nmax); atom->add_callback(0); @@ -278,7 +286,7 @@ FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) : else error->all(FLERR,"Illegal fix rigid command"); if (domain->dimension == 2 && (xflag == 1.0 || yflag == 1.0)) - error->all(FLERR,"Fix rigid xy torque cannot be on for 2d simulation"); + error->all(FLERR,"Fix rigid xy torque cannot be on for 2d simulation"); int count = 0; for (int m = mlo; m <= mhi; m++) { @@ -384,18 +392,24 @@ FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) : // bitmasks for properties of extended particles - INERTIA_POINT = 1; - INERTIA_SPHERE = 2; - INERTIA_ELLIPSOID = 4; - ORIENT_DIPOLE = 8; - ORIENT_QUAT = 16; - OMEGA = 32; - ANGMOM = 64; - TORQUE = 128; + POINT = 1; + SPHERE = 2; + ELLIPSOID = 4; + LINE = 8; + TRIANGLE = 16; + DIPOLE = 32; + OMEGA = 64; + ANGMOM = 128; + TORQUE = 256; + + MINUSPI = -MY_PI; + TWOPI = 2.0*MY_PI; // atom style pointers to particles that store extra info avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + avec_line = (AtomVecLine *) atom->style_match("line"); + avec_tri = (AtomVecTri *) atom->style_match("tri"); // print statistics @@ -423,8 +437,8 @@ FixRigid::~FixRigid() memory->destroy(body); memory->destroy(displace); memory->destroy(eflags); + memory->destroy(orient); memory->destroy(dorient); - memory->destroy(qorient); // delete nbody-length arrays @@ -469,7 +483,7 @@ int FixRigid::setmask() void FixRigid::init() { - int i,ibody; + int i,itype,ibody; triclinic = domain->triclinic; @@ -504,24 +518,33 @@ void FixRigid::init() // extended = 1 if any particle in a rigid body is finite size // or has a dipole moment - extended = dorientflag = qorientflag = 0; + extended = orientflag = dorientflag = 0; AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double **mu = atom->mu; double *radius = atom->radius; double *rmass = atom->rmass; double *mass = atom->mass; int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; int *type = atom->type; int nlocal = atom->nlocal; - if (atom->radius_flag || atom->ellipsoid_flag || atom->mu_flag) { + if (atom->radius_flag || atom->ellipsoid_flag || atom->line_flag || + atom->tri_flag || atom->mu_flag) { int flag = 0; for (i = 0; i < nlocal; i++) { if (body[i] < 0) continue; if (radius && radius[i] > 0.0) flag = 1; if (ellipsoid && ellipsoid[i] >= 0) flag = 1; + if (line && line[i] >= 0) flag = 1; + if (tri && tri[i] >= 0) flag = 1; if (mu && mu[i][3] > 0.0) flag = 1; } @@ -529,35 +552,45 @@ void FixRigid::init() } // grow extended arrays and set extended flags for each particle - // qorientflag = 1 if any particle stores quat orientation + // orientflag = 4 if any particle stores ellipsoid or tri orientation + // orientflag = 1 if any particle stores line orientation // dorientflag = 1 if any particle stores dipole orientation if (extended) { + if (atom->ellipsoid_flag) orientflag = 4; + if (atom->line_flag) orientflag = 1; + if (atom->tri_flag) orientflag = 4; if (atom->mu_flag) dorientflag = 1; - if (atom->ellipsoid_flag) qorientflag = 1; grow_arrays(atom->nmax); for (i = 0; i < nlocal; i++) { eflags[i] = 0; if (body[i] < 0) continue; - // set INERTIA to POINT or SPHERE or ELLIPSOID + // set to POINT or SPHERE or ELLIPSOID or LINE if (radius && radius[i] > 0.0) { - eflags[i] |= INERTIA_SPHERE; + eflags[i] |= SPHERE; eflags[i] |= OMEGA; eflags[i] |= TORQUE; } else if (ellipsoid && ellipsoid[i] >= 0) { - eflags[i] |= INERTIA_ELLIPSOID; - eflags[i] |= ORIENT_QUAT; + eflags[i] |= ELLIPSOID; eflags[i] |= ANGMOM; eflags[i] |= TORQUE; - } else eflags[i] |= INERTIA_POINT; + } else if (line && line[i] >= 0) { + eflags[i] |= LINE; + eflags[i] |= OMEGA; + eflags[i] |= TORQUE; + } else if (tri && tri[i] >= 0) { + eflags[i] |= TRIANGLE; + eflags[i] |= ANGMOM; + eflags[i] |= TORQUE; + } else eflags[i] |= POINT; // set DIPOLE if atom->mu and mu[3] > 0.0 if (atom->mu_flag && mu[i][3] > 0.0) - eflags[i] |= ORIENT_DIPOLE; + eflags[i] |= DIPOLE; } } @@ -592,8 +625,8 @@ void FixRigid::init() if ((xbox && !periodicity[0]) || (ybox && !periodicity[1]) || (zbox && !periodicity[2])) - error->one(FLERR,"Fix rigid atom has non-zero image flag " - "in a non-periodic dimension"); + error->one(FLERR,"Fix rigid atom has non-zero image flag " + "in a non-periodic dimension"); if (triclinic == 0) { xunwrap = x[i][0] + xbox*xprd; @@ -629,7 +662,7 @@ void FixRigid::init() // dx,dy,dz = coords relative to center-of-mass // symmetric 3x3 inertia tensor stored in Voigt notation as 6-vector - double dx,dy,dz; + double dx,dy,dz,rad; for (ibody = 0; ibody < nbody; ibody++) for (i = 0; i < 6; i++) sum[ibody][i] = 0.0; @@ -671,18 +704,19 @@ void FixRigid::init() if (extended) { double ivec[6]; - double *shape,*quatatom; + double *shape,*quatatom,*inertiaatom; + double length,theta; for (i = 0; i < nlocal; i++) { if (body[i] < 0) continue; ibody = body[i]; massone = rmass[i]; - if (eflags[i] & INERTIA_SPHERE) { - sum[ibody][0] += 0.4 * massone * radius[i]*radius[i]; - sum[ibody][1] += 0.4 * massone * radius[i]*radius[i]; - sum[ibody][2] += 0.4 * massone * radius[i]*radius[i]; - } else if (eflags[i] & INERTIA_ELLIPSOID) { + if (eflags[i] & SPHERE) { + sum[ibody][0] += SINERTIA*massone * radius[i]*radius[i]; + sum[ibody][1] += SINERTIA*massone * radius[i]*radius[i]; + sum[ibody][2] += SINERTIA*massone * radius[i]*radius[i]; + } else if (eflags[i] & ELLIPSOID) { shape = ebonus[ellipsoid[i]].shape; quatatom = ebonus[ellipsoid[i]].quat; MathExtra::inertia_ellipsoid(shape,quatatom,massone,ivec); @@ -692,6 +726,26 @@ void FixRigid::init() sum[ibody][3] += ivec[3]; sum[ibody][4] += ivec[4]; sum[ibody][5] += ivec[5]; + } else if (eflags[i] & LINE) { + length = lbonus[line[i]].length; + theta = lbonus[line[i]].theta; + MathExtra::inertia_line(length,theta,massone,ivec); + sum[ibody][0] += ivec[0]; + sum[ibody][1] += ivec[1]; + sum[ibody][2] += ivec[2]; + sum[ibody][3] += ivec[3]; + sum[ibody][4] += ivec[4]; + sum[ibody][5] += ivec[5]; + } else if (eflags[i] & TRIANGLE) { + inertiaatom = tbonus[tri[i]].inertia; + quatatom = tbonus[tri[i]].quat; + MathExtra::inertia_triangle(inertiaatom,quatatom,massone,ivec); + sum[ibody][0] += ivec[0]; + sum[ibody][1] += ivec[1]; + sum[ibody][2] += ivec[2]; + sum[ibody][3] += ivec[3]; + sum[ibody][4] += ivec[4]; + sum[ibody][5] += ivec[5]; } } } @@ -715,7 +769,8 @@ void FixRigid::init() tensor[0][1] = tensor[1][0] = all[ibody][5]; ierror = MathExtra::jacobi(tensor,inertia[ibody],evectors); - if (ierror) error->all(FLERR,"Insufficient Jacobi rotations for rigid body"); + if (ierror) error->all(FLERR, + "Insufficient Jacobi rotations for rigid body"); ex_space[ibody][0] = evectors[0][0]; ex_space[ibody][1] = evectors[1][0]; @@ -756,6 +811,7 @@ void FixRigid::init() double qc[4],delta[3]; double *quatatom; + double theta_body; for (i = 0; i < nlocal; i++) { if (body[i] < 0) { @@ -786,20 +842,34 @@ void FixRigid::init() ez_space[ibody],delta,displace[i]); if (extended) { - if (eflags[i] & ORIENT_DIPOLE) { + if (eflags[i] & ELLIPSOID) { + quatatom = ebonus[ellipsoid[i]].quat; + MathExtra::qconjugate(quat[ibody],qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (eflags[i] & LINE) { + if (quat[ibody][3] >= 0.0) theta_body = 2.0*acos(quat[ibody][0]); + else theta_body = -2.0*acos(quat[ibody][0]); + orient[i][0] = lbonus[line[i]].theta - theta_body; + while (orient[i][0] <= MINUSPI) orient[i][0] += TWOPI; + while (orient[i][0] > MY_PI) orient[i][0] -= TWOPI; + if (orientflag == 4) orient[i][1] = orient[i][2] = orient[i][3] = 0.0; + } else if (eflags[i] & TRIANGLE) { + quatatom = tbonus[tri[i]].quat; + MathExtra::qconjugate(quat[ibody],qc); + MathExtra::quatquat(qc,quatatom,orient[i]); + MathExtra::qnormalize(orient[i]); + } else if (orientflag == 4) { + orient[i][0] = orient[i][1] = orient[i][2] = orient[i][3] = 0.0; + } else if (orientflag == 1) + orient[i][0] = 0.0; + + if (eflags[i] & DIPOLE) { MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody], ez_space[ibody],mu[i],dorient[i]); MathExtra::snormalize3(mu[i][3],dorient[i],dorient[i]); } else if (dorientflag) dorient[i][0] = dorient[i][1] = dorient[i][2] = 0.0; - - if (eflags[i] & ORIENT_QUAT) { - quatatom = ebonus[ellipsoid[i]].quat; - MathExtra::qconjugate(quat[ibody],qc); - MathExtra::quatquat(qc,quatatom,qorient[i]); - MathExtra::qnormalize(qorient[i]); - } else if (qorientflag) - qorient[i][0] = qorient[i][1] = qorient[i][2] = qorient[i][3] = 0.0; } } @@ -831,20 +901,39 @@ void FixRigid::init() if (extended) { double ivec[6]; - double *shape; + double *shape,*inertiaatom; + double length; for (i = 0; i < nlocal; i++) { if (body[i] < 0) continue; ibody = body[i]; massone = rmass[i]; - if (eflags[i] & INERTIA_SPHERE) { - sum[ibody][0] += 0.4 * massone * radius[i]*radius[i]; - sum[ibody][1] += 0.4 * massone * radius[i]*radius[i]; - sum[ibody][2] += 0.4 * massone * radius[i]*radius[i]; - } else if (eflags[i] & INERTIA_ELLIPSOID) { + if (eflags[i] & SPHERE) { + sum[ibody][0] += SINERTIA*massone * radius[i]*radius[i]; + sum[ibody][1] += SINERTIA*massone * radius[i]*radius[i]; + sum[ibody][2] += SINERTIA*massone * radius[i]*radius[i]; + } else if (eflags[i] & ELLIPSOID) { shape = ebonus[ellipsoid[i]].shape; - MathExtra::inertia_ellipsoid(shape,qorient[i],massone,ivec); + MathExtra::inertia_ellipsoid(shape,orient[i],massone,ivec); + sum[ibody][0] += ivec[0]; + sum[ibody][1] += ivec[1]; + sum[ibody][2] += ivec[2]; + sum[ibody][3] += ivec[3]; + sum[ibody][4] += ivec[4]; + sum[ibody][5] += ivec[5]; + } else if (eflags[i] & LINE) { + length = lbonus[line[i]].length; + MathExtra::inertia_line(length,orient[i][0],massone,ivec); + sum[ibody][0] += ivec[0]; + sum[ibody][1] += ivec[1]; + sum[ibody][2] += ivec[2]; + sum[ibody][3] += ivec[3]; + sum[ibody][4] += ivec[4]; + sum[ibody][5] += ivec[5]; + } else if (eflags[i] & TRIANGLE) { + inertiaatom = tbonus[tri[i]].inertia; + MathExtra::inertia_triangle(inertiaatom,orient[i],massone,ivec); sum[ibody][0] += ivec[0]; sum[ibody][1] += ivec[1]; sum[ibody][2] += ivec[2]; @@ -894,7 +983,8 @@ void FixRigid::init() ndof += fflag[ibody][0] + fflag[ibody][1] + fflag[ibody][2]; ndof += tflag[ibody][0] + tflag[ibody][1] + tflag[ibody][2]; } - tfactor = force->mvv2e / (ndof * force->boltz); + if (ndof > 0.0) tfactor = force->mvv2e / (ndof * force->boltz); + else tfactor = 0.0; } /* ---------------------------------------------------------------------- */ @@ -996,24 +1086,29 @@ void FixRigid::setup(int vflag) // extended particles add their rotation/torque to angmom/torque of body if (extended) { + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; double **omega_one = atom->omega; double **angmom_one = atom->angmom; double **torque_one = atom->torque; double *radius = atom->radius; + int *line = atom->line; for (i = 0; i < nlocal; i++) { if (body[i] < 0) continue; ibody = body[i]; if (eflags[i] & OMEGA) { - if (rmass) massone = rmass[i]; - else massone = mass[type[i]]; - radone = radius[i]; - sum[ibody][0] += 0.4 * massone * radone*radone * omega_one[i][0]; - sum[ibody][1] += 0.4 * massone * radone*radone * omega_one[i][1]; - sum[ibody][2] += 0.4 * massone * radone*radone * omega_one[i][2]; + if (eflags[i] & SPHERE) { + radone = radius[i]; + sum[ibody][0] += SINERTIA*rmass[i] * radone*radone * omega_one[i][0]; + sum[ibody][1] += SINERTIA*rmass[i] * radone*radone * omega_one[i][1]; + sum[ibody][2] += SINERTIA*rmass[i] * radone*radone * omega_one[i][2]; + } else if (eflags[i] & LINE) { + radone = lbonus[line[i]].length; + sum[ibody][2] += LINERTIA*rmass[i] * radone*radone * omega_one[i][2]; + } } - if (eflags[i] & ANGMOM) { sum[ibody][0] += angmom_one[i][0]; sum[ibody][1] += angmom_one[i][1]; @@ -1516,7 +1611,7 @@ void FixRigid::deform(int flag) void FixRigid::set_xv() { - int ibody; + int ibody,itype; int xbox,ybox,zbox; double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone; double xy,xz,yz; @@ -1622,43 +1717,64 @@ void FixRigid::set_xv() // set orientation, omega, angmom of each extended particle if (extended) { - double *shape,*quatatom; + double theta_body,theta; + double *shape,*quatatom,*inertiaatom; AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecLine::Bonus *lbonus; + if (avec_line) lbonus = avec_line->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double **omega_one = atom->omega; double **angmom_one = atom->angmom; double **mu = atom->mu; int *ellipsoid = atom->ellipsoid; + int *line = atom->line; + int *tri = atom->tri; for (int i = 0; i < nlocal; i++) { if (body[i] < 0) continue; ibody = body[i]; - - if (eflags[i] & ORIENT_DIPOLE) { - MathExtra::quat_to_mat(quat[ibody],p); - MathExtra::matvec(p,dorient[i],mu[i]); - MathExtra::snormalize3(mu[i][3],mu[i],mu[i]); - } - if (eflags[i] & ORIENT_QUAT) { - quatatom = ebonus[ellipsoid[i]].quat; - MathExtra::quatquat(quat[ibody],qorient[i],quatatom); - MathExtra::qnormalize(quatatom); - } - if (eflags[i] & OMEGA) { + + if (eflags[i] & SPHERE) { omega_one[i][0] = omega[ibody][0]; omega_one[i][1] = omega[ibody][1]; omega_one[i][2] = omega[ibody][2]; - } - if (eflags[i] & ANGMOM) { + } else if (eflags[i] & ELLIPSOID) { shape = ebonus[ellipsoid[i]].shape; quatatom = ebonus[ellipsoid[i]].quat; - ione[0] = 0.2*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]); - ione[1] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]); - ione[2] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]); + MathExtra::quatquat(quat[ibody],orient[i],quatatom); + MathExtra::qnormalize(quatatom); + ione[0] = EINERTIA*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]); + ione[1] = EINERTIA*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]); + ione[2] = EINERTIA*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]); MathExtra::q_to_exyz(quatatom,exone,eyone,ezone); MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone,ione, angmom_one[i]); + } else if (eflags[i] & LINE) { + if (quat[ibody][3] >= 0.0) theta_body = 2.0*acos(quat[ibody][0]); + else theta_body = -2.0*acos(quat[ibody][0]); + theta = orient[i][0] + theta_body; + while (theta <= MINUSPI) theta += TWOPI; + while (theta > MY_PI) theta -= TWOPI; + lbonus[line[i]].theta = theta; + omega_one[i][0] = omega[ibody][0]; + omega_one[i][1] = omega[ibody][1]; + omega_one[i][2] = omega[ibody][2]; + } else if (eflags[i] & TRIANGLE) { + inertiaatom = tbonus[tri[i]].inertia; + quatatom = tbonus[tri[i]].quat; + MathExtra::quatquat(quat[ibody],orient[i],quatatom); + MathExtra::qnormalize(quatatom); + MathExtra::q_to_exyz(quatatom,exone,eyone,ezone); + MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone, + inertiaatom,angmom_one[i]); + } + if (eflags[i] & DIPOLE) { + MathExtra::quat_to_mat(quat[ibody],p); + MathExtra::matvec(p,dorient[i],mu[i]); + MathExtra::snormalize3(mu[i][3],mu[i],mu[i]); } } } @@ -1672,8 +1788,9 @@ void FixRigid::set_xv() void FixRigid::set_v() { - int ibody; + int ibody,itype; int xbox,ybox,zbox; + double dx,dy,dz; double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone; double xy,xz,yz; double ione[3],exone[3],eyone[3],ezone[3],delta[3],vr[6]; @@ -1761,32 +1878,44 @@ void FixRigid::set_v() // set omega, angmom of each extended particle if (extended) { - double *shape,*quatatom; + double *shape,*quatatom,*inertiaatom; AtomVecEllipsoid::Bonus *ebonus; if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus; + AtomVecTri::Bonus *tbonus; + if (avec_tri) tbonus = avec_tri->bonus; double **omega_one = atom->omega; double **angmom_one = atom->angmom; int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; for (int i = 0; i < nlocal; i++) { if (body[i] < 0) continue; ibody = body[i]; - if (eflags[i] & OMEGA) { + if (eflags[i] & SPHERE) { omega_one[i][0] = omega[ibody][0]; omega_one[i][1] = omega[ibody][1]; omega_one[i][2] = omega[ibody][2]; - } - if (eflags[i] & ANGMOM) { + } else if (eflags[i] & ELLIPSOID) { shape = ebonus[ellipsoid[i]].shape; quatatom = ebonus[ellipsoid[i]].quat; - ione[0] = 0.2*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]); - ione[1] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]); - ione[2] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]); + ione[0] = EINERTIA*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]); + ione[1] = EINERTIA*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]); + ione[2] = EINERTIA*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]); MathExtra::q_to_exyz(quatatom,exone,eyone,ezone); MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone,ione, angmom_one[i]); + } else if (eflags[i] & LINE) { + omega_one[i][0] = omega[ibody][0]; + omega_one[i][1] = omega[ibody][1]; + omega_one[i][2] = omega[ibody][2]; + } else if (eflags[i] & TRIANGLE) { + inertiaatom = tbonus[tri[i]].inertia; + quatatom = tbonus[tri[i]].quat; + MathExtra::q_to_exyz(quatatom,exone,eyone,ezone); + MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone, + inertiaatom,angmom_one[i]); } } } @@ -1804,8 +1933,8 @@ double FixRigid::memory_usage() bytes += maxvatom*6 * sizeof(double); if (extended) { bytes += nmax * sizeof(int); + if (orientflag) bytes = nmax*orientflag * sizeof(double); if (dorientflag) bytes = nmax*3 * sizeof(double); - if (qorientflag) bytes = nmax*4 * sizeof(double); } return bytes; } @@ -1820,8 +1949,8 @@ void FixRigid::grow_arrays(int nmax) memory->grow(displace,nmax,3,"rigid:displace"); if (extended) { memory->grow(eflags,nmax,"rigid:eflags"); + if (orientflag) memory->grow(orient,nmax,orientflag,"rigid:orient"); if (dorientflag) memory->grow(dorient,nmax,3,"rigid:dorient"); - if (qorientflag) memory->grow(qorient,nmax,4,"rigid:qorient"); } } @@ -1837,17 +1966,13 @@ void FixRigid::copy_arrays(int i, int j) displace[j][2] = displace[i][2]; if (extended) { eflags[j] = eflags[i]; + for (int k = 0; k < orientflag; k++) + orient[j][k] = orient[i][k]; if (dorientflag) { dorient[j][0] = dorient[i][0]; dorient[j][1] = dorient[i][1]; dorient[j][2] = dorient[i][2]; } - if (qorientflag) { - qorient[j][0] = qorient[i][0]; - qorient[j][1] = qorient[i][1]; - qorient[j][2] = qorient[i][2]; - qorient[j][3] = qorient[i][3]; - } } } @@ -1877,17 +2002,13 @@ int FixRigid::pack_exchange(int i, double *buf) int m = 4; buf[m++] = eflags[i]; + for (int j = 0; j < orientflag; j++) + buf[m++] = orient[i][j]; if (dorientflag) { buf[m++] = dorient[i][0]; buf[m++] = dorient[i][1]; buf[m++] = dorient[i][2]; } - if (qorientflag) { - buf[m++] = qorient[i][0]; - buf[m++] = qorient[i][1]; - buf[m++] = qorient[i][2]; - buf[m++] = qorient[i][3]; - } return m; } @@ -1905,17 +2026,13 @@ int FixRigid::unpack_exchange(int nlocal, double *buf) int m = 4; eflags[nlocal] = static_cast<int> (buf[m++]); + for (int j = 0; j < orientflag; j++) + orient[nlocal][j] = buf[m++]; if (dorientflag) { dorient[nlocal][0] = buf[m++]; dorient[nlocal][1] = buf[m++]; dorient[nlocal][2] = buf[m++]; } - if (qorientflag) { - qorient[nlocal][0] = buf[m++]; - qorient[nlocal][1] = buf[m++]; - qorient[nlocal][2] = buf[m++]; - qorient[nlocal][3] = buf[m++]; - } return m; } diff --git a/src/fix_rigid.h b/src/fix_rigid.h index 06121ad47a..fa803df5f7 100644 --- a/src/fix_rigid.h +++ b/src/fix_rigid.h @@ -56,6 +56,7 @@ class FixRigid : public Fix { double dtv,dtf,dtq; double *step_respa; int triclinic; + double MINUSPI,TWOPI; int nbody; // # of rigid bodies int *nrigid; // # of atoms in each rigid body @@ -82,11 +83,11 @@ class FixRigid : public Fix { int **remapflag; // PBC remap flags for each rigid body int extended; // 1 if any particles have extended attributes + int orientflag; // 1 if particles store spatial orientation int dorientflag; // 1 if particles store dipole orientation - int qorientflag; // 1 if particles store quat orientation int *eflags; // flags for extended particles - double **qorient; // rotation state of ext particle wrt rigid body + double **orient; // orientation vector of particle wrt rigid body double **dorient; // orientation of dipole mu wrt rigid body double tfactor; // scale factor on temperature of rigid bodies @@ -104,10 +105,10 @@ class FixRigid : public Fix { class RanMars *random; class AtomVecEllipsoid *avec_ellipsoid; + class AtomVecLine *avec_line; + class AtomVecTri *avec_tri; - // bitmasks for eflags - int INERTIA_POINT,INERTIA_SPHERE,INERTIA_ELLIPSOID; - int ORIENT_DIPOLE,ORIENT_QUAT; + int POINT,SPHERE,ELLIPSOID,LINE,TRIANGLE,DIPOLE; // bitmasks for eflags int OMEGA,ANGMOM,TORQUE; void no_squish_rotate(int, double *, double *, double *, double); diff --git a/src/read_data.cpp b/src/read_data.cpp index a5a5e47ccb..772c3a3824 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -21,6 +21,8 @@ #include "atom.h" #include "atom_vec.h" #include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" #include "comm.h" #include "update.h" #include "force.h" @@ -42,7 +44,10 @@ using namespace LAMMPS_NS; #define DELTA 4 // must be 2 or larger // customize for new sections -#define NSECTIONS 21 // change when add to header::section_keywords +#define NSECTIONS 23 // change when add to header::section_keywords + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) /* ---------------------------------------------------------------------- */ @@ -60,6 +65,10 @@ ReadData::ReadData(LAMMPS *lmp) : Pointers(lmp) nellipsoids = 0; avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + nlines = 0; + avec_line = (AtomVecLine *) atom->style_match("line"); + ntris = 0; + avec_tri = (AtomVecTri *) atom->style_match("tri"); } /* ---------------------------------------------------------------------- */ @@ -151,7 +160,17 @@ void ReadData::command(int narg, char **arg) if (!avec_ellipsoid) error->all(FLERR,"Invalid data file section: Ellipsoids"); if (atomflag == 0) error->all(FLERR,"Must read Atoms before Ellipsoids"); - ellipsoids(); + bonus(nellipsoids,(AtomVec *) avec_ellipsoid,"ellipsoids"); + } else if (strcmp(keyword,"Lines") == 0) { + if (!avec_line) + error->all(FLERR,"Invalid data file section: Lines"); + if (atomflag == 0) error->all(FLERR,"Must read Atoms before Lines"); + bonus(nlines,(AtomVec *) avec_line,"lines"); + } else if (strcmp(keyword,"Triangles") == 0) { + if (!avec_tri) + error->all(FLERR,"Invalid data file section: Triangles"); + if (atomflag == 0) error->all(FLERR,"Must read Atoms before Triangles"); + bonus(ntris,(AtomVec *) avec_tri,"triangles"); } else if (strcmp(keyword,"Bonds") == 0) { if (atom->avec->bonds_allow == 0) @@ -222,25 +241,31 @@ void ReadData::command(int narg, char **arg) if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: MiddleBondTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before MiddleBondTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before " + "MiddleBondTorsion Coeffs"); dihedralcoeffs(1); } else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: EndBondTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before EndBondTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before EndBondTorsion Coeffs"); dihedralcoeffs(2); } else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: AngleTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before AngleTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before AngleTorsion Coeffs"); dihedralcoeffs(3); } else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: AngleAngleTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before AngleAngleTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before " + "AngleAngleTorsion Coeffs"); dihedralcoeffs(4); } else if (strcmp(keyword,"BondBond13 Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) @@ -274,7 +299,8 @@ void ReadData::command(int narg, char **arg) // error if natoms > 0 yet no atoms were read - if (atom->natoms > 0 && atomflag == 0) error->all(FLERR,"No atoms in data file"); + if (atom->natoms > 0 && atomflag == 0) + error->all(FLERR,"No atoms in data file"); // create bond topology now that system is defined @@ -303,7 +329,7 @@ void ReadData::header(int flag) // customize for new sections char *section_keywords[NSECTIONS] = - {"Atoms","Velocities","Ellipsoids", + {"Atoms","Velocities","Ellipsoids","Lines","Triangles", "Bonds","Angles","Dihedrals","Impropers", "Masses","Pair Coeffs","Bond Coeffs","Angle Coeffs", "Dihedral Coeffs","Improper Coeffs", @@ -373,6 +399,14 @@ void ReadData::header(int flag) if (!avec_ellipsoid) error->all(FLERR,"No ellipsoids allowed with this atom style"); sscanf(line,BIGINT_FORMAT,&nellipsoids); + } else if (strstr(line,"lines")) { + if (!avec_line) + error->all(FLERR,"No lines allowed with this atom style"); + sscanf(line,BIGINT_FORMAT,&nlines); + } else if (strstr(line,"triangles")) { + if (!avec_tri) + error->all(FLERR,"No triangles allowed with this atom style"); + sscanf(line,BIGINT_FORMAT,&ntris); } else if (strstr(line,"xlo xhi")) @@ -475,7 +509,8 @@ void ReadData::atoms() if (logfile) fprintf(logfile," " BIGINT_FORMAT " atoms\n",natoms); } - if (natoms != atom->natoms) error->all(FLERR,"Did not assign all atoms correctly"); + if (natoms != atom->natoms) + error->all(FLERR,"Did not assign all atoms correctly"); // if any atom ID < 0, error // if all atom IDs = 0, tag_enable = 0 @@ -568,11 +603,11 @@ void ReadData::velocities() } /* ---------------------------------------------------------------------- - read all ellipsoids + read all bonus data to find atoms, must build atom map if not a molecular system ------------------------------------------------------------------------- */ -void ReadData::ellipsoids() +void ReadData::bonus(bigint nbonus, AtomVec *ptr, char *type) { int i,m,nchunk; @@ -585,7 +620,7 @@ void ReadData::ellipsoids() } bigint nread = 0; - bigint natoms = nellipsoids; + bigint natoms = nbonus; while (nread < natoms) { if (natoms-nread > CHUNK) nchunk = CHUNK; @@ -603,7 +638,7 @@ void ReadData::ellipsoids() MPI_Bcast(&m,1,MPI_INT,0,world); MPI_Bcast(buffer,m,MPI_CHAR,0,world); - atom->data_bonus(nchunk,buffer,avec_ellipsoid); + atom->data_bonus(nchunk,buffer,ptr); nread += nchunk; } @@ -613,8 +648,8 @@ void ReadData::ellipsoids() } if (me == 0) { - if (screen) fprintf(screen," " BIGINT_FORMAT " ellipsoids\n",natoms); - if (logfile) fprintf(logfile," " BIGINT_FORMAT " ellipsoids\n",natoms); + if (screen) fprintf(screen," " BIGINT_FORMAT " %s\n",natoms,type); + if (logfile) fprintf(logfile," " BIGINT_FORMAT " %s\n",natoms,type); } } @@ -660,7 +695,8 @@ void ReadData::bonds() if (screen) fprintf(screen," " BIGINT_FORMAT " bonds\n",sum/factor); if (logfile) fprintf(logfile," " BIGINT_FORMAT " bonds\n",sum/factor); } - if (sum != factor*atom->nbonds) error->all(FLERR,"Bonds assigned incorrectly"); + if (sum != factor*atom->nbonds) + error->all(FLERR,"Bonds assigned incorrectly"); } /* ---------------------------------------------------------------------- */ @@ -705,7 +741,8 @@ void ReadData::angles() if (screen) fprintf(screen," " BIGINT_FORMAT " angles\n",sum/factor); if (logfile) fprintf(logfile," " BIGINT_FORMAT " angles\n",sum/factor); } - if (sum != factor*atom->nangles) error->all(FLERR,"Angles assigned incorrectly"); + if (sum != factor*atom->nangles) + error->all(FLERR,"Angles assigned incorrectly"); } /* ---------------------------------------------------------------------- */ @@ -1010,6 +1047,8 @@ void ReadData::scan(int &bond_per_atom, int &angle_per_atom, int natoms = static_cast<int> (atom->natoms); bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0; int ellipsoid_flag = 0; + int line_flag = 0; + int tri_flag = 0; // customize for new sections // allocate topology counting vector @@ -1031,6 +1070,14 @@ void ReadData::scan(int &bond_per_atom, int &angle_per_atom, error->all(FLERR,"Invalid data file section: Ellipsoids"); ellipsoid_flag = 1; skip_lines(nellipsoids); + } else if (strcmp(keyword,"Lines") == 0) { + if (!avec_line) error->all(FLERR,"Invalid data file section: Lines"); + line_flag = 1; + skip_lines(nlines); + } else if (strcmp(keyword,"Triangles") == 0) { + if (!avec_tri) error->all(FLERR,"Invalid data file section: Triangles"); + tri_flag = 1; + skip_lines(ntris); } else if (strcmp(keyword,"Pair Coeffs") == 0) { if (force->pair == NULL) @@ -1077,25 +1124,31 @@ void ReadData::scan(int &bond_per_atom, int &angle_per_atom, if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: MiddleBondTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before MiddleBondTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before " + "MiddleBondTorsion Coeffs"); skip_lines(atom->ndihedraltypes); } else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: EndBondTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before EndBondTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before EndBondTorsion Coeffs"); skip_lines(atom->ndihedraltypes); } else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: AngleTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before AngleTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before AngleTorsion Coeffs"); skip_lines(atom->ndihedraltypes); } else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) error->all(FLERR,"Invalid data file section: AngleAngleTorsion Coeffs"); if (force->dihedral == NULL) - error->all(FLERR,"Must define dihedral_style before AngleAngleTorsion Coeffs"); + error->all(FLERR, + "Must define dihedral_style before " + "AngleAngleTorsion Coeffs"); skip_lines(atom->ndihedraltypes); } else if (strcmp(keyword,"BondBond13 Coeffs") == 0) { if (atom->avec->dihedrals_allow == 0) @@ -1252,6 +1305,10 @@ void ReadData::scan(int &bond_per_atom, int &angle_per_atom, if (nellipsoids && !ellipsoid_flag) error->one(FLERR,"Needed bonus data not in data file"); + if (nlines && !line_flag) + error->one(FLERR,"Needed bonus data not in data file"); + if (ntris && !tri_flag) + error->one(FLERR,"Needed bonus data not in data file"); } /* ---------------------------------------------------------------------- diff --git a/src/read_data.h b/src/read_data.h index 80fd441413..67398469c5 100644 --- a/src/read_data.h +++ b/src/read_data.h @@ -40,6 +40,10 @@ class ReadData : protected Pointers { bigint nellipsoids; class AtomVecEllipsoid *avec_ellipsoid; + bigint nlines; + class AtomVecLine *avec_line; + bigint ntris; + class AtomVecTri *avec_tri; void open(char *); void scan(int &, int &, int &, int &); @@ -51,7 +55,7 @@ class ReadData : protected Pointers { void atoms(); void velocities(); - void ellipsoids(); + void bonus(bigint, class AtomVec *, char *); void bonds(); void angles(); diff --git a/src/set.cpp b/src/set.cpp index 4e76dfa2b4..2a4c25731b 100644 --- a/src/set.cpp +++ b/src/set.cpp @@ -19,6 +19,8 @@ #include "atom.h" #include "atom_vec.h" #include "atom_vec_ellipsoid.h" +#include "atom_vec_line.h" +#include "atom_vec_tri.h" #include "domain.h" #include "region.h" #include "group.h" @@ -35,8 +37,8 @@ using namespace LAMMPS_NS; using namespace MathConst; enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT}; -enum{TYPE,TYPE_FRACTION,MOLECULE,X,Y,Z,CHARGE,MASS,SHAPE, - DIPOLE,DIPOLE_RANDOM,QUAT,QUAT_RANDOM, +enum{TYPE,TYPE_FRACTION,MOLECULE,X,Y,Z,CHARGE,MASS,SHAPE,LENGTH,TRI, + DIPOLE,DIPOLE_RANDOM,QUAT,QUAT_RANDOM,THETA,ANGMOM, DIAMETER,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER, MESO_E,MESO_CV,MESO_RHO}; @@ -150,6 +152,22 @@ void Set::command(int narg, char **arg) } set(SHAPE); iarg += 4; + } else if (strcmp(arg[iarg],"length") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + dvalue = atof(arg[iarg+1]); + if (!atom->line_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + if (dvalue < 0.0) error->all(FLERR,"Invalid length in set command"); + set(LENGTH); + iarg += 2; + } else if (strcmp(arg[iarg],"tri") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + dvalue = atof(arg[iarg+1]); + if (!atom->tri_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + if (dvalue < 0.0) error->all(FLERR,"Invalid length in set command"); + set(TRI); + iarg += 2; } else if (strcmp(arg[iarg],"dipole") == 0) { if (iarg+4 > narg) error->all(FLERR,"Illegal set command"); xvalue = atof(arg[iarg+1]); @@ -177,19 +195,36 @@ void Set::command(int narg, char **arg) yvalue = atof(arg[iarg+2]); zvalue = atof(arg[iarg+3]); wvalue = atof(arg[iarg+4]); - if (!atom->ellipsoid_flag) + if (!atom->ellipsoid_flag && !atom->tri_flag) error->all(FLERR,"Cannot set this attribute for this atom style"); set(QUAT); iarg += 5; } else if (strcmp(arg[iarg],"quat/random") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); ivalue = atoi(arg[iarg+1]); - if (!atom->ellipsoid_flag) + if (!atom->ellipsoid_flag && !atom->tri_flag) error->all(FLERR,"Cannot set this attribute for this atom style"); if (ivalue <= 0) error->all(FLERR,"Invalid random number seed in set command"); setrandom(QUAT_RANDOM); iarg += 2; + } else if (strcmp(arg[iarg],"theta") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); + dvalue = atof(arg[iarg+1]); + dvalue *= MY_PI/180.0; + if (!atom->line_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + set(THETA); + iarg += 2; + } else if (strcmp(arg[iarg],"angmom") == 0) { + if (iarg+4 > narg) error->all(FLERR,"Illegal set command"); + xvalue = atof(arg[iarg+1]); + yvalue = atof(arg[iarg+2]); + zvalue = atof(arg[iarg+3]); + if (!atom->ellipsoid_flag && !atom->tri_flag) + error->all(FLERR,"Cannot set this attribute for this atom style"); + set(ANGMOM); + iarg += 4; } else if (strcmp(arg[iarg],"diameter") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal set command"); dvalue = atof(arg[iarg+1]); @@ -385,6 +420,8 @@ void Set::set(int keyword) { AtomVecEllipsoid *avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + AtomVecLine *avec_line = (AtomVecLine *) atom->style_match("line"); + AtomVecTri *avec_tri = (AtomVecTri *) atom->style_match("tri"); selection(atom->nlocal); @@ -405,23 +442,49 @@ void Set::set(int keyword) else if (keyword == MESO_CV) atom->cv[i] = dvalue; else if (keyword == MESO_RHO) atom->rho[i] = dvalue; - // set shape + // set shape of ellipsoidal particle else if (keyword == SHAPE) avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue); + // set length of line particle + + else if (keyword == LENGTH) + avec_line->set_length(i,dvalue); + + // set corners of tri particle + + else if (keyword == TRI) + avec_tri->set_equilateral(i,dvalue); + // set rmass via density // if radius > 0.0, treat as sphere // if shape > 0.0, treat as ellipsoid + // if length > 0.0, treat as line + // if area > 0.0, treat as tri // else set rmass to density directly else if (keyword == DENSITY) { if (atom->radius_flag && atom->radius[i] > 0.0) - atom->rmass[i] = 4.0*MY_PI*THIRD * + atom->rmass[i] = 4.0*MY_PI/3.0 * atom->radius[i]*atom->radius[i]*atom->radius[i] * dvalue; else if (atom->ellipsoid_flag && atom->ellipsoid[i] >= 0) { double *shape = avec_ellipsoid->bonus[atom->ellipsoid[i]].shape; - atom->rmass[i] = 4.0*MY_PI*THIRD * shape[0]*shape[1]*shape[2] * dvalue; + atom->rmass[i] = 4.0*MY_PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue; + } else if (atom->line_flag && atom->line[i] >= 0) { + double length = avec_line->bonus[atom->line[i]].length; + atom->rmass[i] = length * dvalue; + } else if (atom->tri_flag && atom->tri[i] >= 0) { + double *c1 = avec_tri->bonus[atom->tri[i]].c1; + double *c2 = avec_tri->bonus[atom->tri[i]].c2; + double *c3 = avec_tri->bonus[atom->tri[i]].c3; + double c2mc1[2],c3mc1[3]; + MathExtra::sub3(c2,c1,c2mc1); + MathExtra::sub3(c3,c1,c3mc1); + double norm[3]; + MathExtra::cross3(c2mc1,c3mc1,norm); + double area = 0.5 * MathExtra::len3(norm); + atom->rmass[i] = area * dvalue; } else atom->rmass[i] = dvalue; // reset any or all of 3 image flags @@ -446,13 +509,17 @@ void Set::set(int keyword) mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2]); - // set quaternion orientation + // set quaternion orientation of ellipsoid or tri particle } else if (keyword == QUAT) { - if (atom->ellipsoid[i] < 0) - error->one(FLERR, - "Cannot set quaternion for atom that is not an ellipsoid"); - double *quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + double *quat; + if (avec_ellipsoid && atom->ellipsoid[i] >= 0) + quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + else if (avec_tri && atom->tri[i] >= 0) + quat = avec_tri->bonus[atom->tri[i]].quat; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + double theta2 = MY_PI2 * wvalue/180.0; double sintheta2 = sin(theta2); quat[0] = cos(theta2); @@ -460,7 +527,22 @@ void Set::set(int keyword) quat[2] = yvalue * sintheta2; quat[3] = zvalue * sintheta2; MathExtra::qnormalize(quat); + + // set theta of line particle + + } else if (keyword == THETA) { + if (atom->line[i] < 0) + error->one(FLERR,"Cannot set theta for atom that is not a line"); + avec_line->bonus[atom->line[i]].theta = dvalue; + + // set angmom of ellipsoidal or tri particle + + } else if (keyword == ANGMOM) { + atom->angmom[i][0] = xvalue; + atom->angmom[i][1] = yvalue; + atom->angmom[i][2] = zvalue; } + count++; } } @@ -475,6 +557,11 @@ void Set::setrandom(int keyword) { int i; + AtomVecEllipsoid *avec_ellipsoid = + (AtomVecEllipsoid *) atom->style_match("ellipsoid"); + AtomVecLine *avec_line = (AtomVecLine *) atom->style_match("line"); + AtomVecTri *avec_tri = (AtomVecTri *) atom->style_match("tri"); + selection(atom->nlocal); RanPark *random = new RanPark(lmp,1); double **x = atom->x; @@ -535,13 +622,10 @@ void Set::setrandom(int keyword) } // set quaternions to random orientations in 3d or 2d - // no need to normalize quats since creations algorithms already do } else if (keyword == QUAT_RANDOM) { - AtomVecEllipsoid *avec_ellipsoid = - (AtomVecEllipsoid *) atom->style_match("ellipsoid"); - AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus; int *ellipsoid = atom->ellipsoid; + int *tri = atom->tri; int nlocal = atom->nlocal; double *quat; @@ -549,10 +633,13 @@ void Set::setrandom(int keyword) double s,t1,t2,theta1,theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (ellipsoid[i] < 0) - error->one(FLERR,"Cannot set quaternion for atom " - "that is not an ellipsoid"); - quat = bonus[ellipsoid[i]].quat; + if (avec_ellipsoid && atom->ellipsoid[i] >= 0) + quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + else if (avec_tri && atom->tri[i] >= 0) + quat = avec_tri->bonus[atom->tri[i]].quat; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + random->reset(seed,x[i]); s = random->uniform(); t1 = sqrt(1.0-s); @@ -570,10 +657,11 @@ void Set::setrandom(int keyword) double theta2; for (i = 0; i < nlocal; i++) if (select[i]) { - if (ellipsoid[i] < 0) - error->one(FLERR,"Cannot set quaternion for atom " - "that is not an ellipsoid"); - quat = bonus[ellipsoid[i]].quat; + if (avec_ellipsoid && atom->ellipsoid[i] >= 0) + quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat; + else + error->one(FLERR,"Cannot set quaternion for atom that has none"); + random->reset(seed,x[i]); theta2 = MY_PI*random->uniform(); quat[0] = cos(theta2); -- GitLab