Commit 2d5a6938 authored by sjplimp's avatar sjplimp
Browse files

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@2902 f3b2605a-c512-4ea7-a41b-209d697bcdaa
parent 3df8b6e3
Loading
Loading
Loading
Loading
+32 −9
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "compute_erotate_asphere.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "force.h"
#include "memory.h"
@@ -24,19 +25,27 @@ using namespace LAMMPS_NS;

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

ComputeERotateAsphere::ComputeERotateAsphere(LAMMPS *lmp, int narg, char **arg) :
ComputeERotateAsphere::
ComputeERotateAsphere(LAMMPS *lmp, int narg, char **arg) :
  Compute(lmp, narg, arg)
{
  if (narg != 3) error->all("Illegal compute erotate/asphere command");

  if (!atom->angmom_flag || !atom->quat_flag)
    error->all("Compute erotate/asphere requires atom attributes angmom, quat");

  scalar_flag = 1;
  extscalar = 1;

  inertia = 
    memory->create_2d_double_array(atom->ntypes+1,3,"fix_temp_sphere:inertia");

  // error checks

  if (!atom->angmom_flag || !atom->quat_flag ||
      !atom->avec->shape_type)
    error->all("Compute erotate/asphere requires atom attributes "
	       "angmom, quat, shape");
  if (atom->radius_flag || atom->rmass_flag)
    error->all("Compute erotate/asphere cannot be used with atom attributes "
	       "diameter or rmass");
}

/* ---------------------------------------------------------------------- */
@@ -50,11 +59,21 @@ ComputeERotateAsphere::~ComputeERotateAsphere()

void ComputeERotateAsphere::init()
{
  pfactor = 0.5 * force->mvv2e;
  // check that all particles are finite-size
  // no point particles allowed, spherical is OK

  double **shape = atom->shape;
  int *type = atom->type;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  if (!atom->shape)
    error->all("Compute erotate/asphere requires atom attribute shape");
  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit)
      if (shape[type[i]][0] == 0.0)
	error->one("Compue erotate/asphere requires extended particles");

  pfactor = 0.5 * force->mvv2e;
  calculate_inertia();
}

@@ -62,6 +81,8 @@ void ComputeERotateAsphere::init()

double ComputeERotateAsphere::compute_scalar()
{
  int i,itype;

  invoked_scalar = update->ntimestep;

  double **quat = atom->quat;
@@ -70,12 +91,14 @@ double ComputeERotateAsphere::compute_scalar()
  int *type = atom->type;
  int nlocal = atom->nlocal;

  int itype;
  // sum rotational energy for each particle
  // no point particles since divide by inertia

  double wbody[3];
  double rot[3][3];
  double erotate = 0.0;

  for (int i = 0; i < nlocal; i++)
  for (i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {
      itype = type[i];

+57 −54
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "compute_temp_asphere.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "force.h"
#include "domain.h"
@@ -38,9 +39,6 @@ ComputeTempAsphere::ComputeTempAsphere(LAMMPS *lmp, int narg, char **arg) :
  if (narg != 3 && narg != 4)
    error->all("Illegal compute temp/asphere command");

  if (!atom->quat_flag || !atom->angmom_flag)
    error->all("Compute temp/asphere requires atom attributes quat, angmom");

  scalar_flag = vector_flag = 1;
  size_vector = 6;
  extscalar = 0;
@@ -59,6 +57,16 @@ ComputeTempAsphere::ComputeTempAsphere(LAMMPS *lmp, int narg, char **arg) :
  vector = new double[6];
  inertia = 
    memory->create_2d_double_array(atom->ntypes+1,3,"fix_temp_sphere:inertia");

  // error checks

  if (!atom->angmom_flag || !atom->quat_flag ||
      !atom->avec->shape_type)
    error->all("Compute temp/asphere requires atom attributes "
	       "angmom, quat, shape");
  if (atom->radius_flag || atom->rmass_flag)
    error->all("Compute temp/asphere cannot be used with atom attributes "
	       "diameter or rmass");
}

/* ---------------------------------------------------------------------- */
@@ -74,6 +82,20 @@ ComputeTempAsphere::~ComputeTempAsphere()

void ComputeTempAsphere::init()
{
  // check that all particles are finite-size
  // no point particles allowed, spherical is OK

  double **shape = atom->shape;
  int *type = atom->type;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit)
      if (shape[type[i]][0] == 0.0)
	error->one("Compue temp/asphere requires extended particles");

  if (tempbias) {
    int i = modify->find_compute(id_bias);
    if (i < 0) error->all("Could not find compute ID for temperature bias");
@@ -101,43 +123,29 @@ void ComputeTempAsphere::init()

void ComputeTempAsphere::dof_compute()
{
  double natoms = group->count(igroup);
  int dimension = domain->dimension;
  dof = dimension * natoms;
  // 6 dof for 3d, 3 dof for 2d
  // assume full rotation of extended particles
  // user can correct this via compute_modify if needed

  if (tempbias == 1) dof -= tbias->dof_remove(-1) * natoms;
  double natoms = group->count(igroup);
  if (domain->dimension == 3) dof = 6*natoms;
  else dof = 3*natoms;

  // rotational degrees of freedom
  // 0 for sphere, 2 for uniaxial, 3 for biaxial
  // additional adjustments to dof

  double **shape = atom->shape;
  int *type = atom->type;
  if (tempbias == 1) dof -= tbias->dof_remove(-1) * natoms;
  else if (tempbias == 2) {
    int *mask = atom->mask;
    int nlocal = atom->nlocal;

  int itype;
    int count = 0;

    for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {
      if (tempbias == 2 && tbias->dof_remove(i)) continue;
      itype = type[i];
      if (dimension == 2) {
	if (shape[itype][0] == shape[itype][1]) continue;
	else count++;
      } else {
	if (shape[itype][0] == shape[itype][1] && 
	    shape[itype][1] == shape[itype][2]) continue;
	else if (shape[itype][0] == shape[itype][1] || 
		 shape[itype][1] == shape[itype][2] ||
		 shape[itype][0] == shape[itype][2]) count += 2;
	else count += 3;
      }
    }

      if (mask[i] & groupbit)
	if (tbias->dof_remove(i)) count++;
    int count_all;
    MPI_Allreduce(&count,&count_all,1,MPI_INT,MPI_SUM,world);
  dof += count_all;
    if (domain->dimension == 3) dof -= 6*count_all;
    else dof -= 3*count_all;
  }

  dof -= extra_dof + fix_dof;
  if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
@@ -169,32 +177,27 @@ double ComputeTempAsphere::compute_scalar()
  double rot[3][3];
  double t = 0.0;
  
  // sum translationals and rotational energy for each particle
  // no point particles since divide by inertia

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {

      // translational kinetic energy
      
      itype = type[i];
      t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * mass[itype];

      // wbody = angular velocity in body frame
      
      if (!(shape[itype][0] == shape[itype][1] && 
            shape[itype][1] == shape[itype][2])) {

      MathExtra::quat_to_mat(quat[i],rot);
      MathExtra::transpose_times_column3(rot,angmom[i],wbody);
      wbody[0] /= inertia[itype][0];
      wbody[1] /= inertia[itype][1];
      wbody[2] /= inertia[itype][2];

        // rotational kinetic energy

      t += inertia[itype][0]*wbody[0]*wbody[0] +
	inertia[itype][1]*wbody[1]*wbody[1] +
	inertia[itype][2]*wbody[2]*wbody[2];
    }
    }

  if (tempbias) tbias->restore_bias_all();

+61 −22
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "kspace.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"

using namespace LAMMPS_NS;
@@ -38,23 +39,56 @@ enum{NOBIAS,BIAS};
FixNPTAsphere::FixNPTAsphere(LAMMPS *lmp, int narg, char **arg) :
  FixNPT(lmp, narg, arg)
{
  inertia = 
    memory->create_2d_double_array(atom->ntypes+1,3,"fix_npt_asphere:inertia");

  // error checks

  if (!atom->quat_flag || !atom->angmom_flag || !atom->torque_flag ||
      !atom->shape)
      !atom->avec->shape_type)
    error->all("Fix npt/asphere requires atom attributes "
	       "quat, angmom, torque, shape");
  if (atom->radius_flag || atom->rmass_flag)
    error->all("Fix npt/asphere cannot be used with atom attributes "
	       "diameter or rmass");
}

/* ----------------------------------------------------------------------
   1st half of Verlet update 
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */

FixNPTAsphere::~FixNPTAsphere()
{
  memory->destroy_2d_double_array(inertia);
}

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

void FixNPTAsphere::init()
{
  // check that all particles are finite-size
  // no point particles allowed, spherical is OK

  double **shape = atom->shape;
  int *type = atom->type;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit)
      if (shape[type[i]][0] == 0.0)
	error->one("Fix nvt/asphere requires extended particles");

  FixNPT::init();
  calculate_inertia();
}

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

void FixNPTAsphere::initial_integrate(int vflag)
{
  int i;
  double dtfm;

  dtq = 0.5 * dtv;

  double delta = update->ntimestep - update->beginstep;
  delta /= update->endstep - update->beginstep;

@@ -85,8 +119,6 @@ void FixNPTAsphere::initial_integrate(int vflag)
  }
  factor_rotate = exp(-dthalf*eta_dot);

  // update v of only atoms in group

  double **x = atom->x;
  double **v = atom->v;
  double **f = atom->f;
@@ -135,7 +167,11 @@ void FixNPTAsphere::initial_integrate(int vflag)
    }
  }

  // update angular momentum by 1/2 step
  // set timestep here since dt may have changed or come via rRESPA

  dtq = 0.5 * dtv;

  // update angular momentum by 1/2 step for all particles
  // update quaternion a full step via Richardson iteration
  // returns new normalized quaternion

@@ -145,9 +181,7 @@ void FixNPTAsphere::initial_integrate(int vflag)
      angmom[i][1] = angmom[i][1]*factor_rotate + dtf*torque[i][1];
      angmom[i][2] = angmom[i][2]*factor_rotate + dtf*torque[i][2];
		
      double inertia[3];
      calculate_inertia(atom->mass[type[i]],atom->shape[type[i]],inertia);
      richardson(quat[i],angmom[i],inertia);
      richardson(quat[i],angmom[i],inertia[type[i]]);
    }
  }

@@ -158,9 +192,7 @@ void FixNPTAsphere::initial_integrate(int vflag)
  if (kspace_flag) force->kspace->setup();
}

/* ----------------------------------------------------------------------
   2nd half of Verlet update 
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */

void FixNPTAsphere::final_integrate()
{
@@ -320,15 +352,22 @@ void FixNPTAsphere::omega_from_mq(double *q, double *m, double *inertia,
  MathExtra::times_column3(rot,wbody,w);
}


/* ----------------------------------------------------------------------
   calculate the moment of inertia for an ellipsoid, from mass and radii
   shape = x,y,z radii in body frame
   principal moments of inertia for ellipsoids
------------------------------------------------------------------------- */

void FixNPTAsphere::calculate_inertia(double mass, double *shape,
				      double *inertia)
void FixNPTAsphere::calculate_inertia()
{
  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]);
  double *mass = atom->mass;
  double **shape = atom->shape;
  
  for (int i = 1; i <= atom->ntypes; i++) {
    inertia[i][0] = 0.2*mass[i] *
      (shape[i][1]*shape[i][1]+shape[i][2]*shape[i][2]);
    inertia[i][1] = 0.2*mass[i] *
      (shape[i][0]*shape[i][0]+shape[i][2]*shape[i][2]);
    inertia[i][2] = 0.2*mass[i] * 
      (shape[i][0]*shape[i][0]+shape[i][1]*shape[i][1]);
  }
}
+4 −1
Original line number Diff line number Diff line
@@ -21,16 +21,19 @@ namespace LAMMPS_NS {
class FixNPTAsphere : public FixNPT {
 public:
  FixNPTAsphere(class LAMMPS *, int, char **);
  ~FixNPTAsphere();
  void init();
  void initial_integrate(int);
  void final_integrate();

 private:
  double dtq;
  double factor_rotate;
  double **inertia;

  void richardson(double *, double *, double *);
  void omega_from_mq(double *, double *, double *, double *);
  void calculate_inertia(double mass, double *shape, double *inertia);
  void calculate_inertia();
};

}
+30 −8
Original line number Diff line number Diff line
@@ -37,12 +37,18 @@ using namespace LAMMPS_NS;
FixNVEAsphere::FixNVEAsphere(LAMMPS *lmp, int narg, char **arg) : 
  FixNVE(lmp, narg, arg)
{
  if (!atom->quat_flag || !atom->angmom_flag || !atom->torque_flag ||
      !atom->shape)
    error->all("Fix nve/asphere requires atom attributes "
	       "quat, angmom, torque, shape");
  inertia = 
    memory->create_2d_double_array(atom->ntypes+1,3,"fix_temp_sphere:inertia");
    memory->create_2d_double_array(atom->ntypes+1,3,"fix_nve_asphere:inertia");

  // error checks

  if (!atom->angmom_flag || !atom->quat_flag || !atom->torque_flag ||
      !atom->avec->shape_type)
    error->all("Fix nve/asphere requires atom attributes "
	       "angmom, quat, torque, shape");
  if (atom->radius_flag || atom->rmass_flag)
    error->all("Fix nve/asphere cannot be used with atom attributes "
	       "diameter or rmass");
}

/* ---------------------------------------------------------------------- */
@@ -56,6 +62,20 @@ FixNVEAsphere::~FixNVEAsphere()

void FixNVEAsphere::init()
{
  // check that all particles are finite-size
  // no point particles allowed, spherical is OK

  double **shape = atom->shape;
  int *type = atom->type;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit)
      if (shape[type[i]][0] == 0.0)
	error->one("Fix nve/asphere requires extended particles");

  FixNVE::init();
  calculate_inertia();
}
@@ -66,8 +86,6 @@ void FixNVEAsphere::initial_integrate(int vflag)
{
  double dtfm;

  dtq = 0.5 * dtv;

  double **x = atom->x;
  double **v = atom->v;
  double **f = atom->f;
@@ -80,6 +98,10 @@ void FixNVEAsphere::initial_integrate(int vflag)
  int nlocal = atom->nlocal;
  if (igroup == atom->firstgroup) nlocal = atom->nfirst;

  // set timestep here since dt may have changed or come via rRESPA

  dtq = 0.5 * dtv;

  for (int i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {
      dtfm = dtf / mass[type[i]];
Loading