Commit 322ed027 authored by sjplimp's avatar sjplimp
Browse files

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@3642 f3b2605a-c512-4ea7-a41b-209d697bcdaa
parent 056c4e38
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -119,6 +119,10 @@ void Domain::init()
	deform_groupbit = modify->fix[i]->groupbit;
      } else deform_remap = 0;
    }

  // region inits

  for (int i = 0; i < nregion; i++) regions[i]->init();
}

/* ----------------------------------------------------------------------
+63 −0
Original line number Diff line number Diff line
/* ----------------------------------------------------------------------
   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
   http://lammps.sandia.gov, Sandia National Laboratories
   Steve Plimpton, sjplimp@sandia.gov

   Copyright (2003) Sandia Corporation.  Under the terms of Contract
   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
   certain rights in this software.  This software is distributed under 
   the GNU General Public License.

   See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */

#include "math.h"
#include "fix_wall_harmonic.h"
#include "atom.h"
#include "error.h"

using namespace LAMMPS_NS;

/* ---------------------------------------------------------------------- */

FixWallHarmonic::FixWallHarmonic(LAMMPS *lmp, int narg, char **arg) : 
  FixWall(lmp, narg, arg) {}

/* ----------------------------------------------------------------------
   interaction of all particles in group with all 6 walls (if defined)
   error if any particle is on or behind wall
------------------------------------------------------------------------- */

void FixWallHarmonic::wall_particle(int m, double coord)
{
  double delta,dr,fwall;

  double **x = atom->x;
  double **f = atom->f;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  int dim = m/2;
  int side = m % 2;
  if (side == 0) side = -1;

  int onflag = 0;

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {
      if (side < 0) delta = x[i][dim] - coord;
      else delta = coord - x[i][dim];
      if (delta >= cutoff[m]) continue;
      if (delta <= 0.0) {
	onflag = 1;
	continue;
      }
      dr = cutoff[m]-delta;
      fwall = side * 2.0*epsilon[m]*dr;
      f[i][dim] -= fwall;
      ewall[0] += epsilon[m]*dr*dr;
      ewall[m+1] += fwall;
    }

  if (onflag) error->one("Particle on or inside fix wall surface");
}
+33 −0
Original line number Diff line number Diff line
/* ----------------------------------------------------------------------
   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
   http://lammps.sandia.gov, Sandia National Laboratories
   Steve Plimpton, sjplimp@sandia.gov

   Copyright (2003) Sandia Corporation.  Under the terms of Contract
   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
   certain rights in this software.  This software is distributed under 
   the GNU General Public License.

   See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */

#ifndef FIX_WALL_HARMONIC_H
#define FIX_WALL_HARMONIC_H

#include "fix_wall.h"

namespace LAMMPS_NS {

class FixWallHarmonic : public FixWall {
 public:
  FixWallHarmonic(class LAMMPS *, int, char **);
  void precompute(int) {}
  void wall_particle(int, double);

 private:
  double offset[6];
};

}

#endif
+1 −1
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ void FixWallRegion::post_force(int vflag)
      if (style == COLLOID) tooclose = shape[type[i]][0];
      else tooclose = 0.0;

      n = region->surface(x[i],cutoff);
      n = region->surface(x[i][0],x[i][1],x[i][2],cutoff);

      for (m = 0; m < n; m++) {
	if (region->contact[m].r <= tooclose) {
+204 −3
Original line number Diff line number Diff line
@@ -15,12 +15,15 @@
#include "stdlib.h"
#include "string.h"
#include "region.h"
#include "update.h"
#include "domain.h"
#include "lattice.h"
#include "error.h"

using namespace LAMMPS_NS;

enum{NONE,LINEAR,WIGGLE,ROTATE,VARIABLE};

/* ---------------------------------------------------------------------- */

Region::Region(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
@@ -32,6 +35,8 @@ Region::Region(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
  n = strlen(arg[1]) + 1;
  style = new char[n];
  strcpy(style,arg[1]);

  time_origin = update->ntimestep;
}

/* ---------------------------------------------------------------------- */
@@ -42,6 +47,13 @@ Region::~Region()
  delete [] style;
}

/* ---------------------------------------------------------------------- */

void Region::init()
{
  dt = update->dt;
}

/* ----------------------------------------------------------------------
   parse optional parameters at end of region input line
------------------------------------------------------------------------- */
@@ -54,6 +66,7 @@ void Region::options(int narg, char **arg)

  interior = 1;
  scaleflag = 1;
  dynamic = NONE;

  int iarg = 0;
  while (iarg < narg) {
@@ -69,9 +82,41 @@ void Region::options(int narg, char **arg)
      else if (strcmp(arg[iarg+1],"out") == 0) interior = 0;
      else error->all("Illegal region command");
      iarg += 2;
    } else if (strcmp(arg[iarg],"linear") == 0) {
      if (iarg+4 > narg) error->all("Illegal region command");
      vx = atof(arg[iarg+1]);
      vy = atof(arg[iarg+2]);
      vz = atof(arg[iarg+3]);
      dynamic = LINEAR;
      iarg += 4;
    } else if (strcmp(arg[iarg],"wiggle") == 0) {
      if (iarg+5 > narg) error->all("Illegal region command");
      ax = atof(arg[iarg+1]);
      ay = atof(arg[iarg+2]);
      az = atof(arg[iarg+3]);
      period = atof(arg[iarg+4]);
      dynamic = WIGGLE;
      iarg += 5;
    } else if (strcmp(arg[iarg],"rotate") == 0) {
      if (iarg+8 > narg) error->all("Illegal region command");
      point[0] = atof(arg[iarg+1]);
      point[1] = atof(arg[iarg+2]);
      point[2] = atof(arg[iarg+3]);
      axis[0] = atof(arg[iarg+4]);
      axis[1] = atof(arg[iarg+5]);
      axis[2] = atof(arg[iarg+6]);
      period = atof(arg[iarg+7]);
      dynamic = ROTATE;
      iarg += 8;
    } else error->all("Illegal region command");
  }

  // error check
  
  if (dynamic && 
      (strcmp(style,"union") == 0 || strcmp(style,"intersect") == 0))
    error->all("Region union or intersect cannot be dynamic");

  // setup scaling

  if (scaleflag && domain->lattice == NULL)
@@ -83,16 +128,128 @@ void Region::options(int narg, char **arg)
    zscale = domain->lattice->zlattice;
  }
  else xscale = yscale = zscale = 1.0;

  if (dynamic == LINEAR) {
    vx *= xscale;
    vy *= yscale;
    vz *= zscale;
  } else if (dynamic == WIGGLE) {
    ax *= xscale;
    ay *= yscale;
    az *= zscale;
  } else if (dynamic == ROTATE) {
    point[0] *= xscale;
    point[1] *= yscale;
    point[2] *= zscale;
  }

  if (dynamic == WIGGLE || dynamic == ROTATE) {
    double PI = 4.0 * atan(1.0);
    omega_rotate = 2.0*PI / period;
  }

  // runit = unit vector along rotation axis

  if (dynamic == ROTATE) {
    double len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
    if (len == 0.0) 
      error->all("Region cannot have 0 length rotation vector");
    runit[0] = axis[0]/len;
    runit[1] = axis[1]/len;
    runit[2] = axis[2]/len;
  }
}

/* ----------------------------------------------------------------------
   determine if point x,y,z is a match to region volume
   XOR computes 0 if 2 args are the same, 1 if different
   note that inside() returns 1 for points on surface of region
   thus point on surface of exterior region will not match
   if region is dynamic, apply inverse of region change to x
------------------------------------------------------------------------- */

int Region::match(double x, double y, double z)
{
  double a[3],b[3],c[3],d[3],disp[0];

  if (dynamic) {
    double delta = (update->ntimestep - time_origin) * dt;
    if (dynamic == LINEAR) {
      x -= vx*delta;
      y -= vy*delta;
      z -= vz*delta;
    } else if (dynamic == WIGGLE) {
      double arg = omega_rotate * delta;
      double sine = sin(arg);
      x -= ax*sine;
      y -= ay*sine;
      z -= az*sine;
    } else if (dynamic == ROTATE) {
      double angle = -omega_rotate*delta;
      rotate(x,y,z,angle);
    }
  }

  return !(inside(x,y,z) ^ interior);
}

/* ----------------------------------------------------------------------
   generate list of contact points for interior or exterior regions
   if region is dynamic:
     change x by inverse of region change
     change contact point by region change
------------------------------------------------------------------------- */

int Region::surface(double *x, double cutoff)
int Region::surface(double x, double y, double z, double cutoff)
{
  if (interior) return surface_interior(x,cutoff);
  return surface_exterior(x,cutoff);
  int ncontact;
  double xnear[3],xhold[3];

  if (dynamic) {
    double delta = (update->ntimestep - time_origin) * dt;
    if (dynamic == LINEAR) {
      x -= vx*delta;
      y -= vy*delta;
      z -= vz*delta;
    } else if (dynamic == WIGGLE) {
      double arg = omega_rotate * delta;
      double sine = sin(arg);
      x -= ax*sine;
      y -= ay*sine;
      z -= az*sine;
    } else if (dynamic == ROTATE) {
      xhold[0] = x;
      xhold[1] = y;
      xhold[2] = z;
      double angle = -omega_rotate*delta;
      rotate(x,y,z,angle);
    }
  }

  xnear[0] = x;
  xnear[1] = y;
  xnear[2] = z;

  if (interior) ncontact = surface_interior(xnear,cutoff);
  else ncontact = surface_exterior(xnear,cutoff);

  if (dynamic && ncontact) {
    double delta = (update->ntimestep - time_origin) * dt;
    if (dynamic == ROTATE) {
      for (int i = 0; i < ncontact; i++) {
	x -= contact[i].delx;
	y -= contact[i].dely;
	z -= contact[i].delz;
	double angle = omega_rotate*delta;
	rotate(x,y,z,angle);
	contact[i].delx = xhold[0] - x;
	contact[i].dely = xhold[1] - y;
	contact[i].delz = xhold[2] - z;
      }
    }
  }

  return ncontact;
}

/* ----------------------------------------------------------------------
@@ -111,3 +268,47 @@ void Region::add_contact(int n, double *x, double xp, double yp, double zp)
  contact[n].dely = dely;
  contact[n].delz = delz;
}

/* ----------------------------------------------------------------------
   rotate x,y,z by angle via right-hand rule around point and runit normal
   sign of angle determines whether rotating forward/backward in time
   return updated x,y,z
   P = point = vector = point of rotation
   R = vector = axis of rotation
   w = omega of rotation (from period)
   X0 = x,y,z = initial coord of atom
   R0 = runit = unit vector for R
   C = (X0 dot R0) R0 = projection of atom coord onto R
   D = X0 - P = vector from P to X0
   A = D - C = vector from R line to X0
   B = R0 cross A = vector perp to A in plane of rotation
   A,B define plane of circular rotation around R line
   x,y,z = P + C + A cos(w*dt) + B sin(w*dt)
------------------------------------------------------------------------- */

void Region::rotate(double &x, double &y, double &z, double angle)
{
  double a[3],b[3],c[3],d[3],disp[0];

  double sine = sin(angle);
  double cosine = cos(angle);
  double x0dotr = x*runit[0] + y*runit[1] + z*runit[2]; 
  c[0] = x0dotr * runit[0];
  c[1] = x0dotr * runit[1];
  c[2] = x0dotr * runit[2];
  d[0] = x - point[0];
  d[1] = y - point[1];
  d[2] = z - point[2];
  a[0] = d[0] - c[0];
  a[1] = d[1] - c[1];
  a[2] = d[2] - c[2];
  b[0] = runit[1]*a[2] - runit[2]*a[1];
  b[1] = runit[2]*a[0] - runit[0]*a[2];
  b[2] = runit[0]*a[1] - runit[1]*a[0];
  disp[0] = a[0]*cosine  + b[0]*sine;
  disp[1] = a[1]*cosine  + b[1]*sine;
  disp[2] = a[2]*cosine  + b[2]*sine;
  x = point[0] + c[0] + disp[0];
  y = point[1] + c[1] + disp[1];
  z = point[2] + c[2] + disp[2];
}
Loading