Added hexatic bond orientational order parameter

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@14231 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
athomps
2015-11-04 05:18:21 +00:00
parent c8c2f18edd
commit f227080d70
5 changed files with 461 additions and 0 deletions

BIN
doc/Eqs/hexorder.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

8
doc/Eqs/hexorder.tex Normal file
View File

@ -0,0 +1,8 @@
\documentclass[12pt]{article}
\begin{document}
$$
q_6 = \frac{1}{N_{neigh}}\sum_{j = 1}^{N_{neigh}} e^{6 i \theta({\bf r}_{ij})}
$$
\end{document}

View File

@ -0,0 +1,117 @@
"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
:link(lws,http://lammps.sandia.gov)
:link(ld,Manual.html)
:link(lc,Section_commands.html#comm)
:line
compute hexorder/atom command :h3
[Syntax:]
compute ID group-ID hexorder/atom cutoff type1 type2 ... :pre
ID, group-ID are documented in "compute"_compute.html command
hexorder/atom = style name of this compute command
cutoff = distance within which to count neighbors (distance units)
typeN = atom type for Nth order parameter (see asterisk form below) :ul
[Examples:]
compute 1 all hexorder/atom 2.0
compute 1 all hexorder/atom 6.0 1 2
compute 1 all hexorder/atom 6.0 2*4 5*8 * :pre
[Description:]
Define a computation that calculates one or more hexatic bond orientational
order parameters for each atom in a group. The hexatic bond orientational order
parameter {q}6 "(Nelson)"_#Nelson for an atom is a complex number (stored as two real numbers).
It is defined as follows:
:c,image(Eqs/hexorder.jpg)
where the sum is over atoms of the specified atom type(s) that are within
the specified cutoff distance from the central atom. The angle theta
is formed by the bond vector rij and the {x} axis. theta is calculated
only using the {x} and {y} components, whereas the distance from the
central atom is calculated using all three
{x}, {y}, and {z} components of the bond vector.
Atoms not in the group
are included in the order parameter of atoms in the group.
If the neighbors of the central atom lie on a hexagonal lattice,
then |{q}6| = 1.
The complex phase of {q}6 depends on the orientation of the
lattice relative to the {x} axis. For a liquid in which the
atomic neighborhood lacks orientational symmettry, |{q}6| << 1.
The {typeN} keywords allow you to specify which atom types contribute
to each order parameter. One order parameter is computed for
each of the {typeN} keywords listed. If no {typeN} keywords are
listed, a single order parameter is calculated, which includes
atoms of all types (same as the "*" format, see below).
The {typeN} keywords can be specified in one of two ways. An explicit
numeric value can be used, as in the 2nd example above. Or a
wild-card asterisk can be used to specify a range of atom types. This
takes the form "*" or "*n" or "n*" or "m*n". If N = the number of
atom types, then an asterisk with no numeric values means all types
from 1 to N. A leading asterisk means all types from 1 to n
(inclusive). A trailing asterisk means all types from n to N
(inclusive). A middle asterisk means all types from m to n
(inclusive).
The value of all order parameters will be 0.0+0.0i for atoms not in the
specified compute group. An order parameter for atoms that have no
neighbors of the specified atom type within the cutoff distance will
be 0.0+0.0i.
The neighbor list needed to compute this quantity is constructed each
time the calculation is performed (i.e. each time a snapshot of atoms
is dumped). Thus it can be inefficient to compute/dump this quantity
too frequently.
IMPORTANT NOTE: If you have a bonded system, then the settings of
"special_bonds"_special_bonds.html command can remove pairwise
interactions between atoms in the same bond, angle, or dihedral. This
is the default setting for the "special_bonds"_special_bonds.html
command, and means those pairwise interactions do not appear in the
neighbor list. Because this fix uses the neighbor list, it also means
those pairs will not be included in the order parameter. One way
to get around this, is to write a dump file, and use the
"rerun"_rerun.html command to compute the order parameter for snapshots
in the dump file. The rerun script can use a
"special_bonds"_special_bonds.html command that includes all pairs in
the neighbor list.
[Output info:]
If single {type1} keyword is specified (or if none are specified),
this compute calculates a per-atom array with 2 columns, giving the
real and imaginary parts of the order parameter, respectively.
If multiple {typeN} keywords are specified, this compute calculates
a per-atom array with 2*N columns, with each consecutive pair of
columns giving the real and imaginary parts of one order parameter.
These values can be accessed by any command that uses
per-atom values from a compute as input. See "Section_howto
15"_Section_howto.html#howto_15 for an overview of LAMMPS output
options.
The per-atom array values will be floating point numbers, as
explained above.
[Restrictions:] none
[Related commands:]
"compute coord/atom"_compute_coord_atom.html
[Default:] none
:line
:link(Nelson)
[(Nelson)] Nelson, Halperin, Phys Rev B, 19, 2457 (1979).

View File

@ -0,0 +1,263 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "compute_hexorder_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeHexOrderAtom::ComputeHexOrderAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
if (narg < 4) error->all(FLERR,"Illegal compute hexorder/atom command");
double cutoff = force->numeric(FLERR,arg[3]);
cutsq = cutoff*cutoff;
ncol = narg-4 + 1;
int ntypes = atom->ntypes;
typelo = new int[ncol];
typehi = new int[ncol];
if (narg == 4) {
ncol = 2;
typelo[0] = 1;
typehi[0] = ntypes;
} else {
ncol = 0;
int iarg = 4;
while (iarg < narg) {
force->bounds(arg[iarg],ntypes,typelo[ncol],typehi[ncol]);
if (typelo[ncol] > typehi[ncol])
error->all(FLERR,"Illegal compute hexorder/atom command");
typelo[ncol+1] = typelo[ncol];
typehi[ncol+1] = typehi[ncol];
ncol+=2;
iarg++;
}
}
peratom_flag = 1;
size_peratom_cols = ncol;
nmax = 0;
q6array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeHexOrderAtom::~ComputeHexOrderAtom()
{
delete [] typelo;
delete [] typehi;
memory->destroy(q6array);
}
/* ---------------------------------------------------------------------- */
void ComputeHexOrderAtom::init()
{
if (force->pair == NULL)
error->all(FLERR,"Compute hexorder/atom requires a pair style be defined");
if (sqrt(cutsq) > force->pair->cutforce)
error->all(FLERR,
"Compute hexorder/atom cutoff is longer than pairwise cutoff");
// need an occasional full neighbor list
int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"hexorder/atom") == 0) count++;
if (count > 1 && comm->me == 0)
error->warning(FLERR,"More than one compute hexorder/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeHexOrderAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeHexOrderAtom::compute_peratom()
{
int i,j,m,ii,jj,inum,jnum,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
double *count;
invoked_peratom = update->ntimestep;
// grow coordination array if necessary
if (atom->nlocal > nmax) {
memory->destroy(q6array);
nmax = atom->nmax;
memory->create(q6array,nmax,ncol,"hexorder/atom:q6array");
array_atom = q6array;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// compute order parameter(s) for each atom in group
// use full neighbor list to count atoms less than cutoff
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
if (ncol == 2) {
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double* q6 = q6array[i];
q6[0] = q6[1] = 0.0;
if (mask[i] & groupbit) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
double usum = 0.0;
double vsum = 0.0;
int ncount = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq && jtype >= typelo[0] && jtype <= typehi[0]) {
double u, v;
calc_q6(delx, dely, u, v);
usum += u;
vsum += v;
ncount++;
}
}
if (ncount > 0) {
double ninv = 1.0/ncount ;
q6[0] = usum*ninv;
q6[1] = vsum*ninv;
}
}
}
} else {
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double* q6 = q6array[i];
for (m = 0; m < ncol; m++) q6[m] = 0.0;
if (mask[i] & groupbit) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
for (m = 0; m < ncol; m+=2) {
double usum = 0.0;
double vsum = 0.0;
int ncount = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
if (jtype >= typelo[m] && jtype <= typehi[m]) {
double u, v;
calc_q6(delx, dely, u, v);
usum += u;
vsum += v;
ncount++;
}
}
if (ncount > 0) {
double ninv = 1.0/ncount ;
q6[m] = usum*ninv;
q6[m+1] = vsum*ninv;
}
}
}
}
}
}
}
inline void ComputeHexOrderAtom::calc_q6(double delx, double dely, double &u, double &v) {
double rinv = 1.0/sqrt(delx*delx+dely*dely);
double x = delx*rinv;
double y = dely*rinv;
double a = x*x;
double b1 = y*y;
double b2 = b1*b1;
double b3 = b2*b1;
u = (( a - 15*b1)*a + 15*b2)*a - b3;
v = ((6*a - 20*b1)*a + 6*b2)*x*y;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeHexOrderAtom::memory_usage()
{
double bytes = ncol*nmax * sizeof(double);
return bytes;
}

View File

@ -0,0 +1,73 @@
/* -*- c++ -*- ----------------------------------------------------------
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.
------------------------------------------------------------------------- */
#ifdef COMPUTE_CLASS
ComputeStyle(hexorder/atom,ComputeHexOrderAtom)
#else
#ifndef LMP_COMPUTE_HEXORDER_ATOM_H
#define LMP_COMPUTE_HEXORDER_ATOM_H
#include "compute.h"
namespace LAMMPS_NS {
class ComputeHexOrderAtom : public Compute {
public:
ComputeHexOrderAtom(class LAMMPS *, int, char **);
~ComputeHexOrderAtom();
void init();
void init_list(int, class NeighList *);
void compute_peratom();
double memory_usage();
private:
int nmax,ncol;
double cutsq;
class NeighList *list;
int *typelo,*typehi;
double **q6array;
void calc_q6(double, double, double&, double&);
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
E: Compute hexorder/atom requires a pair style be defined
Self-explantory.
E: Compute hexorder/atom cutoff is longer than pairwise cutoff
Cannot compute order parameter at distances longer than the pair cutoff,
since those atoms are not in the neighbor list.
W: More than one compute hexorder/atom
It is not efficient to use compute hexorder/atom more than once.
*/