git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9512 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2013-02-15 17:36:53 +00:00
parent f57f4ec774
commit 00be9561e7
8 changed files with 5076 additions and 0 deletions

View File

@ -0,0 +1,461 @@
/* ----------------------------------------------------------------------
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 "string.h"
#include "stdlib.h"
#include "fix_nphug_omp.h"
#include "modify.h"
#include "error.h"
#include "update.h"
#include "compute.h"
#include "force.h"
#include "domain.h"
#include "group.h"
#include "math.h"
#include "memory.h"
#include "comm.h"
#include "math.h"
using namespace LAMMPS_NS;
using namespace FixConst;
enum{ISO,ANISO,TRICLINIC}; // same as fix_nh.cpp
/* ---------------------------------------------------------------------- */
FixNPHugOMP::FixNPHugOMP(LAMMPS *lmp, int narg, char **arg) :
FixNHOMP(lmp, narg, arg)
{
// Prevent masses from being updated every timestep
eta_mass_flag = 0;
omega_mass_flag = 0;
etap_mass_flag = 0;
// extend vector of base-class computes
size_vector += 3;
// turn off deviatoric flag and remove strain energy from vector
deviatoric_flag = 0;
size_vector -= 1;
// use initial state as reference state
v0_set = p0_set = e0_set = 0;
// check pressure settings
if (p_start[0] != p_stop[0] ||
p_start[1] != p_stop[1] ||
p_start[2] != p_stop[2])
error->all(FLERR,"Pstart and Pstop must have the same value");
// uniaxial = 0 means hydrostatic compression
// uniaxial = 1 means uniaxial compression
// in x, y, or z (idir = 0, 1, or 2)
// isotropic hydrostatic compression
if (pstyle == ISO) {
uniaxial = 0;
// anisotropic compression
} else if (pstyle == ANISO) {
// anisotropic hydrostatic compression
if (p_start[0] == p_start[1] &&
p_start[0] == p_start[2] )
uniaxial = 0;
// uniaxial compression
else if (p_flag[0] == 1 && p_flag[1] == 0
&& p_flag[2] == 0) {
uniaxial = 1;
idir = 0;
} else if (p_flag[0] == 0 && p_flag[1] == 1
&& p_flag[2] == 0) {
uniaxial = 1;
idir = 1;
} else if (p_flag[0] == 0 && p_flag[1] == 0
&& p_flag[2] == 1) {
uniaxial = 1;
idir = 2;
} else error->all(FLERR,"Specified target stress must be uniaxial or hydrostatic");
// triclinic hydrostatic compression
} else if (pstyle == TRICLINIC) {
if (p_start[0] == p_start[1] &&
p_start[0] == p_start[2] &&
p_start[3] == 0.0 &&
p_start[4] == 0.0 &&
p_start[5] == 0.0 )
uniaxial = 0;
else error->all(FLERR,"For triclinic deformation, specified target stress must be hydrostatic");
}
if (!tstat_flag)
error->all(FLERR,"Temperature control must be used with fix nphug/omp");
if (!pstat_flag)
error->all(FLERR,"Pressure control must be used with fix nphug/omp");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
// create a new compute potential energy compute
n = strlen(id) + 3;
id_pe = new char[n];
strcpy(id_pe,id);
strcat(id_pe,"_pe");
newarg = new char*[3];
newarg[0] = id_pe;
newarg[1] = (char*)"all";
newarg[2] = (char*)"pe";
modify->add_compute(3,newarg);
delete [] newarg;
peflag = 1;
}
/* ---------------------------------------------------------------------- */
FixNPHugOMP::~FixNPHugOMP()
{
// temp and press computes handled by base class
// delete pe compute
if (peflag) modify->delete_compute(id_pe);
delete [] id_pe;
}
/* ---------------------------------------------------------------------- */
void FixNPHugOMP::init()
{
// Call base class init()
FixNHOMP::init();
// set pe ptr
int icompute = modify->find_compute(id_pe);
if (icompute < 0)
error->all(FLERR,"Potential energy ID for fix nvt/nph/npt does not exist");
pe = modify->compute[icompute];
}
/* ----------------------------------------------------------------------
compute initial state before integrator starts
------------------------------------------------------------------------- */
void FixNPHugOMP::setup(int vflag)
{
FixNHOMP::setup(vflag);
if ( v0_set == 0 ) {
v0 = compute_vol();
v0_set = 1;
}
if ( p0_set == 0 ) {
p0_set = 1;
if (uniaxial == 1)
p0 = p_current[idir];
else
p0 = (p_current[0]+p_current[1]+p_current[2])/3.0;
}
if ( e0_set == 0 ) {
e0 = compute_etotal();
e0_set = 1;
}
double masstot = group->mass(igroup);
rho0 = nktv2p*force->mvv2e*masstot/v0;
t_target = 0.01;
pe->addstep(update->ntimestep+1);
}
/* ----------------------------------------------------------------------
compute target temperature and kinetic energy
-----------------------------------------------------------------------*/
void FixNPHugOMP::compute_temp_target()
{
t_target = t_current + compute_hugoniot();
ke_target = tdof * boltz * t_target;
pe->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
double FixNPHugOMP::compute_etotal()
{
double epot,ekin,etot;
epot = pe->compute_scalar();
if (thermo_energy) epot -= compute_scalar();
ekin = temperature->compute_scalar();
ekin *= 0.5 * tdof * force->boltz;
etot = epot+ekin;
return etot;
}
/* ---------------------------------------------------------------------- */
double FixNPHugOMP::compute_vol()
{
if (domain->dimension == 3)
return domain->xprd * domain->yprd * domain->zprd;
else
return domain->xprd * domain->yprd;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point
from the Hugoniot in temperature units.
------------------------------------------------------------------------- */
double FixNPHugOMP::compute_hugoniot()
{
double v,e,p;
double dhugo;
e = compute_etotal();
temperature->compute_vector();
if (uniaxial == 1) {
pressure->compute_vector();
p = pressure->vector[idir];
} else
p = pressure->compute_scalar();
v = compute_vol();
dhugo = (0.5 * (p + p0 ) * ( v0 - v)) /
force->nktv2p + e0 - e;
dhugo /= tdof * boltz;
return dhugo;
}
/* ----------------------------------------------------------------------
Compute shock velocity is distance/time units
------------------------------------------------------------------------- */
double FixNPHugOMP::compute_us()
{
double v,p;
double eps,us;
temperature->compute_vector();
if (uniaxial == 1) {
pressure->compute_vector();
p = pressure->vector[idir];
} else
p = pressure->compute_scalar();
v = compute_vol();
// Us^2 = (p-p0)/(rho0*eps)
eps = 1.0 - v/v0;
if (eps < 1.0e-10) us = 0.0;
else if (p < p0) us = 0.0;
else us = sqrt((p-p0)/(rho0*eps));
return us;
}
/* ----------------------------------------------------------------------
Compute particle velocity is distance/time units
------------------------------------------------------------------------- */
double FixNPHugOMP::compute_up()
{
double v;
double eps,us,up;
v = compute_vol();
us = compute_us();
// u = eps*Us
eps = 1.0 - v/v0;
up = us*eps;
return up;
}
// look for index in local class
// if index not found, look in base class
double FixNPHugOMP::compute_vector(int n)
{
int ilen;
// n = 0: Hugoniot energy difference (temperature units)
ilen = 1;
if (n < ilen) return compute_hugoniot();
n -= ilen;
// n = 1: Shock velocity
ilen = 1;
if (n < ilen) return compute_us();
n -= ilen;
// n = 2: Particle velocity
ilen = 1;
if (n < ilen) return compute_up();
n -= ilen;
// index not found, look in base class
return FixNHOMP::compute_vector(n);
}
/* ----------------------------------------------------------------------
pack restart data
------------------------------------------------------------------------- */
int FixNPHugOMP::pack_restart_data(double *list)
{
int n = 0;
list[n++] = e0;
list[n++] = v0;
list[n++] = p0;
// call the base class function
n += FixNHOMP::pack_restart_data(list+n);
return n;
}
/* ----------------------------------------------------------------------
calculate the number of data to be packed
------------------------------------------------------------------------- */
int FixNPHugOMP::size_restart_global()
{
int nsize = 3;
// call the base class function
nsize += FixNHOMP::size_restart_global();
return nsize;
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixNPHugOMP::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
e0 = list[n++];
v0 = list[n++];
p0 = list[n++];
e0_set = 1;
v0_set = 1;
p0_set = 1;
// call the base class function
buf += n*sizeof(double);
FixNHOMP::restart(buf);
}
/* ---------------------------------------------------------------------- */
int FixNPHugOMP::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"e0") == 0) {
if (narg < 2) error->all(FLERR,"Illegal fix nphug/omp command");
e0 = atof(arg[1]);
e0_set = 1;
return 2;
} else if (strcmp(arg[0],"v0") == 0) {
if (narg < 2) error->all(FLERR,"Illegal fix nphug/omp command");
v0 = atof(arg[1]);
v0_set = 1;
return 2;
} else if (strcmp(arg[0],"p0") == 0) {
if (narg < 2) error->all(FLERR,"Illegal fix nphug/omp command");
p0 = atof(arg[1]);
p0_set = 1;
return 2;
}
return 0;
}

View File

@ -0,0 +1,98 @@
/* -*- 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 FIX_CLASS
FixStyle(nphug/omp,FixNPHugOMP)
#else
#ifndef LMP_FIX_NPHUG_OMP_H
#define LMP_FIX_NPHUG_OMP_H
#include "fix_nh_omp.h"
namespace LAMMPS_NS {
class FixNPHugOMP : public FixNHOMP {
public:
FixNPHugOMP(class LAMMPS *, int, char **);
virtual ~FixNPHugOMP();
virtual void init();
virtual void setup(int);
virtual int modify_param(int, char **);
virtual int pack_restart_data(double *); // pack restart data
virtual void restart(char *);
private:
class Compute *pe; // PE compute pointer
void compute_temp_target();
double compute_vector(int);
double compute_etotal();
double compute_vol();
double compute_hugoniot();
double compute_us();
double compute_up();
char *id_pe;
int peflag;
int v0_set,p0_set,e0_set;
double v0,p0,e0,rho0;
int idir;
int uniaxial;
int size_restart_global();
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Pstart and Pstop must have the same value
Self-explanatory.
E: Specified target stress must be uniaxial or hydrostatic
Self-explanatory.
E: For triclinic deformation, specified target stress must be hydrostatic
Triclinic pressure control is allowed using the tri keyword, but
non-hydrostatic pressure control can not be used in this case.
E: Temperature control must be used with fix nphug
The temp keyword must be provided.
E: Pressure control must be used with fix nphug
A pressure control keyword (iso, aniso, tri, x, y, or z) must be
provided.
E: Potential energy ID for fix nvt/nph/npt does not exist
A compute for potential energy must be defined.
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.
*/

View File

@ -0,0 +1,620 @@
/* ----------------------------------------------------------------------
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: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "fix_rigid_small_omp.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "atom_vec_line.h"
#include "atom_vec_tri.h"
#include "comm.h"
#include "domain.h"
#include <string.h>
#if defined(_OPENMP)
#include <omp.h>
#endif
#include "math_extra.h"
#include "math_const.h"
using namespace LAMMPS_NS;
using namespace FixConst;
using namespace MathConst;
#define EINERTIA 0.4 // moment of inertia prefactor for ellipsoid
enum{FULL_BODY,INITIAL,FINAL,FORCE_TORQUE,VCM_ANGMOM,XCM_MASS,ITENSOR,DOF};
typedef struct { double x,y,z; } dbl3_t;
#if defined(__GNUC__)
#define _noalias __restrict
#else
#define _noalias
#endif
/* ---------------------------------------------------------------------- */
void FixRigidSmallOMP::initial_integrate(int vflag)
{
int ibody;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) schedule(static)
#endif
for (ibody = 0; ibody < nlocal_body; ibody++) {
Body &b = body[ibody];
// update vcm by 1/2 step
const double dtfm = dtf / b.mass;
b.vcm[0] += dtfm * b.fcm[0];
b.vcm[1] += dtfm * b.fcm[1];
b.vcm[2] += dtfm * b.fcm[2];
// update xcm by full step
b.xcm[0] += dtv * b.vcm[0];
b.xcm[1] += dtv * b.vcm[1];
b.xcm[2] += dtv * b.vcm[2];
// update angular momentum by 1/2 step
b.angmom[0] += dtf * b.torque[0];
b.angmom[1] += dtf * b.torque[1];
b.angmom[2] += dtf * b.torque[2];
// compute omega at 1/2 step from angmom at 1/2 step and current q
// update quaternion a full step via Richardson iteration
// returns new normalized quaternion, also updated omega at 1/2 step
// update ex,ey,ez to reflect new quaternion
MathExtra::angmom_to_omega(b.angmom,b.ex_space,b.ey_space,
b.ez_space,b.inertia,b.omega);
MathExtra::richardson(b.quat,b.angmom,b.omega,b.inertia,dtq);
MathExtra::q_to_exyz(b.quat,b.ex_space,b.ey_space,b.ez_space);
} // end of omp parallel for
// virial setup before call to set_xv
if (vflag) v_setup(vflag);
else evflag = 0;
// forward communicate updated info of all bodies
commflag = INITIAL;
comm->forward_comm_variable_fix(this);
// set coords/orient and velocity/rotation of atoms in rigid bodies
if (triclinic)
if (evflag)
set_xv_thr<1,1>();
else
set_xv_thr<1,0>();
else
if (evflag)
set_xv_thr<0,1>();
else
set_xv_thr<0,0>();
}
/* ---------------------------------------------------------------------- */
void FixRigidSmallOMP::final_integrate()
{
double * const * _noalias const x = atom->x;
const dbl3_t * _noalias const f = (dbl3_t *) atom->f[0];
const double * const * const torque_one = atom->torque;
const tagint * _noalias const image = atom->image;
const int nlocal = atom->nlocal;
const int nthreads=comm->nthreads;
int i, ibody;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) schedule(static)
#endif
for (ibody = 0; ibody < nlocal_body+nghost_body; ibody++) {
double * _noalias const fcm = body[ibody].fcm;
fcm[0] = fcm[1] = fcm[2] = 0.0;
double * _noalias const tcm = body[ibody].torque;
tcm[0] = tcm[1] = tcm[2] = 0.0;
}
// sum over atoms to get force and torque on rigid body
// we likely have a large number of rigid objects with only a
// a few atoms each. so we loop over all atoms for all threads
// and then each thread only processes some bodies.
#if defined(_OPENMP)
#pragma omp parallel default(none) private(i,ibody)
#endif
{
#if defined(_OPENMP)
const int tid = omp_get_thread_num();
#else
const int tid = 0;
#endif
for (i = 0; i < nlocal; i++) {
ibody = atom2body[i];
if ((ibody < 0) || (ibody % nthreads != tid)) continue;
Body &b = body[ibody];
double unwrap[3];
domain->unmap(x[i],image[i],unwrap);
double * _noalias const fcm = b.fcm;
double * _noalias const xcm = b.xcm;
double * _noalias const tcm = b.torque;
const double dx = unwrap[0] - xcm[0];
const double dy = unwrap[1] - xcm[1];
const double dz = unwrap[2] - xcm[2];
fcm[0] += f[i].x;
fcm[1] += f[i].y;
fcm[2] += f[i].z;
tcm[0] += dy*f[i].z - dz*f[i].y;
tcm[1] += dz*f[i].x - dx*f[i].z;
tcm[2] += dx*f[i].y - dy*f[i].x;
if (extended && (eflags[i] & TORQUE)) {
tcm[0] += torque_one[i][0];
tcm[1] += torque_one[i][1];
tcm[2] += torque_one[i][2];
}
}
} // end of omp parallel region
// reverse communicate fcm, torque of all bodies
commflag = FORCE_TORQUE;
comm->reverse_comm_variable_fix(this);
// include Langevin thermostat forces and torques
if (langflag) {
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) schedule(static)
#endif
for (ibody = 0; ibody < nlocal_body; ibody++) {
double * _noalias const fcm = body[ibody].fcm;
fcm[0] += langextra[ibody][0];
fcm[1] += langextra[ibody][1];
fcm[2] += langextra[ibody][2];
double * _noalias const tcm = body[ibody].torque;
tcm[0] += langextra[ibody][3];
tcm[1] += langextra[ibody][4];
tcm[2] += langextra[ibody][5];
}
}
// update vcm and angmom, recompute omega
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) schedule(static)
#endif
for (ibody = 0; ibody < nlocal_body; ibody++) {
Body &b = body[ibody];
// update vcm by 1/2 step
const double dtfm = dtf / b.mass;
b.vcm[0] += dtfm * b.fcm[0];
b.vcm[1] += dtfm * b.fcm[1];
b.vcm[2] += dtfm * b.fcm[2];
// update angular momentum by 1/2 step
b.angmom[0] += dtf * b.torque[0];
b.angmom[1] += dtf * b.torque[1];
b.angmom[2] += dtf * b.torque[2];
MathExtra::angmom_to_omega(b.angmom,b.ex_space,b.ey_space,
b.ez_space,b.inertia,b.omega);
}
// forward communicate updated info of all bodies
commflag = FINAL;
comm->forward_comm_variable_fix(this);
// set velocity/rotation of atoms in rigid bodies
// virial is already setup from initial_integrate
// triclinic only matters for virial calculation.
if (evflag)
if (triclinic)
set_v_thr<1,1>();
else
set_v_thr<0,1>();
else
set_v_thr<0,0>();
}
/* ----------------------------------------------------------------------
set space-frame coords and velocity of each atom in each rigid body
set orientation and rotation of extended particles
x = Q displace + Xcm, mapped back to periodic box
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
template <int TRICLINIC, int EVFLAG>
void FixRigidSmallOMP::set_xv_thr()
{
dbl3_t * _noalias const x = (dbl3_t *) atom->x[0];
dbl3_t * _noalias const v = (dbl3_t *) atom->v[0];
const dbl3_t * _noalias const f = (dbl3_t *) atom->f[0];
const double * _noalias const rmass = atom->rmass;
const double * _noalias const mass = atom->mass;
const int * _noalias const type = atom->type;
const tagint * _noalias const image = atom->image;
double v0=0.0,v1=0.0,v2=0.0,v3=0.0,v4=0.0,v5=0.0;
const double xprd = domain->xprd;
const double yprd = domain->yprd;
const double zprd = domain->zprd;
const double xy = domain->xy;
const double xz = domain->xz;
const double yz = domain->yz;
// set x and v of each atom
const int nlocal = atom->nlocal;
int i;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) reduction(+:v0,v1,v2,v3,v4,v5)
#endif
for (i = 0; i < nlocal; i++) {
const int ibody = atom2body[i];
if (ibody < 0) continue;
Body &b = body[ibody];
const int xbox = (image[i] & IMGMASK) - IMGMAX;
const int ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX;
const int zbox = (image[i] >> IMG2BITS) - IMGMAX;
const double deltax = xbox*xprd + (TRICLINIC ? ybox*xy + zbox*xz : 0.0);
const double deltay = ybox*yprd + (TRICLINIC ? zbox*yz : 0.0);
const double deltaz = zbox*zprd;
// save old positions and velocities for virial
double x0,x1,x2,vx,vy,vz;
if (EVFLAG) {
x0 = x[i].x + deltax;
x1 = x[i].y + deltay;
x2 = x[i].z + deltaz;
vx = v[i].x;
vy = v[i].y;
vz = v[i].z;
}
// x = displacement from center-of-mass, based on body orientation
// v = vcm + omega around center-of-mass
MathExtra::matvec(b.ex_space,b.ey_space,b.ez_space,displace[i],&x[i].x);
v[i].x = b.omega[1]*x[i].z - b.omega[2]*x[i].y + b.vcm[0];
v[i].y = b.omega[2]*x[i].x - b.omega[0]*x[i].z + b.vcm[1];
v[i].z = b.omega[0]*x[i].y - b.omega[1]*x[i].x + b.vcm[2];
// add center of mass to displacement
// map back into periodic box via xbox,ybox,zbox
// for triclinic, add in box tilt factors as well
x[i].x += b.xcm[0] - deltax;
x[i].y += b.xcm[1] - deltay;
x[i].z += b.xcm[2] - deltaz;
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c final_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (EVFLAG) {
double massone,vr[6];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
const double fc0 = 0.5*(massone*(v[i].x - vx)/dtf - f[i].x);
const double fc1 = 0.5*(massone*(v[i].y - vy)/dtf - f[i].y);
const double fc2 = 0.5*(massone*(v[i].z - vz)/dtf - f[i].z);
vr[0] = x0*fc0; vr[1] = x1*fc1; vr[2] = x2*fc2;
vr[3] = x0*fc1; vr[4] = x0*fc2; vr[5] = x1*fc2;
// Fix::v_tally() is not thread safe, so we do this manually here
// accumulate global virial into thread-local variables for reduction
if (vflag_global) {
v0 += vr[0];
v1 += vr[1];
v2 += vr[2];
v3 += vr[3];
v4 += vr[4];
v5 += vr[5];
}
// accumulate per atom virial directly since we parallelize over atoms.
if (vflag_atom) {
vatom[i][0] += vr[0];
vatom[i][1] += vr[1];
vatom[i][2] += vr[2];
vatom[i][3] += vr[3];
vatom[i][4] += vr[4];
vatom[i][5] += vr[5];
}
}
}
// second part of thread safe virial accumulation
// add global virial component after it was reduced across all threads
if (EVFLAG) {
if (vflag_global) {
virial[0] += v0;
virial[1] += v1;
virial[2] += v2;
virial[3] += v3;
virial[4] += v4;
virial[5] += v5;
}
}
// set orientation, omega, angmom of each extended particle
// XXX: extended particle info not yet multi-threaded
if (extended) {
double ione[3],exone[3],eyone[3],ezone[3],p[3][3];
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 = atom->omega;
double **angmom = 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 (atom2body[i] < 0) continue;
Body &b = body[atom2body[i]];
if (eflags[i] & SPHERE) {
omega[i][0] = b.omega[0];
omega[i][1] = b.omega[1];
omega[i][2] = b.omega[2];
} else if (eflags[i] & ELLIPSOID) {
shape = ebonus[ellipsoid[i]].shape;
quatatom = ebonus[ellipsoid[i]].quat;
MathExtra::quatquat(b.quat,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(b.omega,exone,eyone,ezone,ione,angmom[i]);
} else if (eflags[i] & LINE) {
if (b.quat[3] >= 0.0) theta_body = 2.0*acos(b.quat[0]);
else theta_body = -2.0*acos(b.quat[0]);
theta = orient[i][0] + theta_body;
while (theta <= MINUSPI) theta += TWOPI;
while (theta > MY_PI) theta -= TWOPI;
lbonus[line[i]].theta = theta;
omega[i][0] = b.omega[0];
omega[i][1] = b.omega[1];
omega[i][2] = b.omega[2];
} else if (eflags[i] & TRIANGLE) {
inertiaatom = tbonus[tri[i]].inertia;
quatatom = tbonus[tri[i]].quat;
MathExtra::quatquat(b.quat,orient[i],quatatom);
MathExtra::qnormalize(quatatom);
MathExtra::q_to_exyz(quatatom,exone,eyone,ezone);
MathExtra::omega_to_angmom(b.omega,exone,eyone,ezone,
inertiaatom,angmom[i]);
}
if (eflags[i] & DIPOLE) {
MathExtra::quat_to_mat(b.quat,p);
MathExtra::matvec(p,dorient[i],mu[i]);
MathExtra::snormalize3(mu[i][3],mu[i],mu[i]);
}
}
}
}
/* ----------------------------------------------------------------------
set space-frame velocity of each atom in a rigid body
set omega and angmom of extended particles
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
template <int TRICLINIC, int EVFLAG>
void FixRigidSmallOMP::set_v_thr()
{
dbl3_t * _noalias const x = (dbl3_t *) atom->x[0];
dbl3_t * _noalias const v = (dbl3_t *) atom->v[0];
const dbl3_t * _noalias const f = (dbl3_t *) atom->f[0];
const double * _noalias const rmass = atom->rmass;
const double * _noalias const mass = atom->mass;
const int * _noalias const type = atom->type;
const tagint * _noalias const image = atom->image;
const double xprd = domain->xprd;
const double yprd = domain->yprd;
const double zprd = domain->zprd;
const double xy = domain->xy;
const double xz = domain->xz;
const double yz = domain->yz;
double v0=0.0,v1=0.0,v2=0.0,v3=0.0,v4=0.0,v5=0.0;
// set v of each atom
const int nlocal = atom->nlocal;
int i;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) reduction(+:v0,v1,v2,v3,v4,v5)
#endif
for (i = 0; i < nlocal; i++) {
const int ibody = atom2body[i];
if (ibody < 0) continue;
Body &b = body[atom2body[i]];
double delta[3],vx,vy,vz;
MathExtra::matvec(b.ex_space,b.ey_space,b.ez_space,displace[i],delta);
// save old velocities for virial
if (EVFLAG) {
vx = v[i].x;
vy = v[i].y;
vz = v[i].z;
}
v[i].x = b.omega[1]*delta[2] - b.omega[2]*delta[1] + b.vcm[0];
v[i].y = b.omega[2]*delta[0] - b.omega[0]*delta[2] + b.vcm[1];
v[i].z = b.omega[0]*delta[1] - b.omega[1]*delta[0] + b.vcm[2];
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c initial_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (EVFLAG) {
double massone, vr[6];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
const int xbox = (image[i] & IMGMASK) - IMGMAX;
const int ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX;
const int zbox = (image[i] >> IMG2BITS) - IMGMAX;
const double deltax = xbox*xprd + (TRICLINIC ? ybox*xy + zbox*xz : 0.0);
const double deltay = ybox*yprd + (TRICLINIC ? zbox*yz : 0.0);
const double deltaz = zbox*zprd;
const double fc0 = 0.5*(massone*(v[i].x - vx)/dtf - f[i].x);
const double fc1 = 0.5*(massone*(v[i].y - vy)/dtf - f[i].y);
const double fc2 = 0.5*(massone*(v[i].z - vz)/dtf - f[i].z);
const double x0 = x[i].x + deltax;
const double x1 = x[i].y + deltay;
const double x2 = x[i].z + deltaz;
vr[0] = x0*fc0; vr[1] = x1*fc1; vr[2] = x2*fc2;
vr[3] = x0*fc1; vr[4] = x0*fc2; vr[5] = x1*fc2;
// Fix::v_tally() is not thread safe, so we do this manually here
// accumulate global virial into thread-local variables and reduce them later
if (vflag_global) {
v0 += vr[0];
v1 += vr[1];
v2 += vr[2];
v3 += vr[3];
v4 += vr[4];
v5 += vr[5];
}
// accumulate per atom virial directly since we parallelize over atoms.
if (vflag_atom) {
vatom[i][0] += vr[0];
vatom[i][1] += vr[1];
vatom[i][2] += vr[2];
vatom[i][3] += vr[3];
vatom[i][4] += vr[4];
vatom[i][5] += vr[5];
}
}
} // end of parallel for
// second part of thread safe virial accumulation
// add global virial component after it was reduced across all threads
if (EVFLAG) {
if (vflag_global) {
virial[0] += v0;
virial[1] += v1;
virial[2] += v2;
virial[3] += v3;
virial[4] += v4;
virial[5] += v5;
}
}
// set omega, angmom of each extended particle
// XXX: extended particle info not yet multi-threaded
if (extended) {
double ione[3],exone[3],eyone[3],ezone[3];
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 = atom->omega;
double **angmom = atom->angmom;
int *ellipsoid = atom->ellipsoid;
int *tri = atom->tri;
for (int i = 0; i < nlocal; i++) {
if (atom2body[i] < 0) continue;
Body &b = body[atom2body[i]];
if (eflags[i] & SPHERE) {
omega[i][0] = b.omega[0];
omega[i][1] = b.omega[1];
omega[i][2] = b.omega[2];
} else if (eflags[i] & ELLIPSOID) {
shape = ebonus[ellipsoid[i]].shape;
quatatom = ebonus[ellipsoid[i]].quat;
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(b.omega,exone,eyone,ezone,ione,
angmom[i]);
} else if (eflags[i] & LINE) {
omega[i][0] = b.omega[0];
omega[i][1] = b.omega[1];
omega[i][2] = b.omega[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(b.omega,exone,eyone,ezone,
inertiaatom,angmom[i]);
}
}
}
}

View File

@ -0,0 +1,134 @@
/* -*- 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 FIX_CLASS
FixStyle(rigid/small/omp,FixRigidSmallOMP)
#else
#ifndef LMP_FIX_RIGID_SMALL_OMP_H
#define LMP_FIX_RIGID_SMALL_OMP_H
#include "fix_rigid_small.h"
namespace LAMMPS_NS {
class FixRigidSmallOMP : public FixRigidSmall {
public:
FixRigidSmallOMP(class LAMMPS *lmp, int narg, char **args)
: FixRigidSmall(lmp,narg,args) {};
virtual ~FixRigidSmallOMP() {};
virtual void initial_integrate(int);
virtual void final_integrate();
private:
template <int, int> void set_xv_thr();
template <int, int> void set_v_thr();
};
}
#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: Fix rigid molecule requires atom attribute molecule
Self-explanatory.
E: Could not find fix rigid group ID
A group ID used in the fix rigid command does not exist.
E: One or more atoms belong to multiple rigid bodies
Two or more rigid bodies defined by the fix rigid command cannot
contain the same atom.
E: No rigid bodies defined
The fix specification did not end up defining any rigid bodies.
E: Fix rigid z force cannot be on for 2d simulation
Self-explanatory.
E: Fix rigid xy torque cannot be on for 2d simulation
Self-explanatory.
E: Fix rigid langevin period must be > 0.0
Self-explanatory.
E: One or zero atoms in rigid body
Any rigid body defined by the fix rigid command must contain 2 or more
atoms.
W: More than one fix rigid
It is not efficient to use fix rigid more than once.
E: Rigid fix must come before NPT/NPH fix
NPT/NPH fix must be defined in input script after all rigid fixes,
else the rigid fix contribution to the pressure virial is
incorrect.
W: Computing temperature of portions of rigid bodies
The group defined by the temperature compute does not encompass all
the atoms in one or more rigid bodies, so the change in
degrees-of-freedom for the atoms in those partial rigid bodies will
not be accounted for.
E: Fix rigid atom has non-zero image flag in a non-periodic dimension
You cannot set image flags for non-periodic dimensions.
E: Insufficient Jacobi rotations for rigid body
Eigensolve for rigid body was not sufficiently accurate.
E: Fix rigid: Bad principal moments
The principal moments of inertia computed for a rigid body
are not within the required tolerances.
E: Cannot open fix rigid infile %s
UNDOCUMENTED
E: Unexpected end of fix rigid file
UNDOCUMENTED
E: Incorrect rigid body format in fix rigid file
UNDOCUMENTED
E: Invalid rigid body ID in fix rigid file
UNDOCUMENTED
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/* -*- 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 KSPACE_CLASS
KSpaceStyle(pppm/disp/omp,PPPMDispOMP)
#else
#ifndef LMP_PPPM_DISP_OMP_H
#define LMP_PPPM_DISP_OMP_H
#include "pppm_disp.h"
#include "thr_omp.h"
namespace LAMMPS_NS {
class PPPMDispOMP : public PPPMDisp, public ThrOMP {
public:
PPPMDispOMP(class LAMMPS *, int, char **);
virtual ~PPPMDispOMP () {};
virtual void compute(int, int);
protected:
virtual void allocate();
virtual void deallocate();
virtual void compute_gf();
virtual void compute_gf_6();
virtual void particle_map(double,double,double,
double,int**,int,int,
int,int,int,int,int,int);
virtual void fieldforce_c_ik();
virtual void fieldforce_c_ad();
virtual void fieldforce_c_peratom();
virtual void fieldforce_g_ik();
virtual void fieldforce_g_ad();
virtual void fieldforce_g_peratom();
virtual void fieldforce_a_ik();
virtual void fieldforce_a_ad();
virtual void fieldforce_a_peratom();
virtual void make_rho_c();
virtual void make_rho_g();
virtual void make_rho_a();
void compute_rho1d_thr(FFT_SCALAR * const * const, const FFT_SCALAR &,
const FFT_SCALAR &, const FFT_SCALAR &,
const int, FFT_SCALAR * const * const);
void compute_drho1d_thr(FFT_SCALAR * const * const, const FFT_SCALAR &,
const FFT_SCALAR &, const FFT_SCALAR &,
const int, FFT_SCALAR * const * const);
// void compute_rho_coeff();
// void slabcorr(int);
};
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/* -*- 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 KSPACE_CLASS
KSpaceStyle(pppm/disp/tip4p/omp,PPPMDispTIP4POMP)
#else
#ifndef LMP_PPPM_DISP_TIP4P_OMP_H
#define LMP_PPPM_DISP_TIP4P_OMP_H
#include "pppm_disp_tip4p.h"
#include "thr_omp.h"
namespace LAMMPS_NS {
class PPPMDispTIP4POMP : public PPPMDispTIP4P, public ThrOMP {
public:
PPPMDispTIP4POMP(class LAMMPS *, int, char **);
virtual ~PPPMDispTIP4POMP () {};
protected:
virtual void allocate();
virtual void deallocate();
virtual void compute_gf();
virtual void compute_gf_6();
virtual void compute(int,int);
virtual void particle_map(double, double, double,
double, int **, int, int,
int, int, int, int, int, int);
virtual void particle_map_c(double, double, double,
double, int **, int, int,
int, int, int, int, int, int);
virtual void make_rho_c(); // XXX: not (yet) multi-threaded
virtual void make_rho_g();
virtual void make_rho_a();
virtual void fieldforce_c_ik();
virtual void fieldforce_c_ad();
// virtual void fieldforce_peratom(); XXX: need to benchmark first.
virtual void fieldforce_g_ik();
virtual void fieldforce_g_ad();
virtual void fieldforce_g_peratom();
virtual void fieldforce_a_ik();
virtual void fieldforce_a_ad();
virtual void fieldforce_a_peratom();
private:
void compute_rho1d_thr(FFT_SCALAR * const * const, const FFT_SCALAR &,
const FFT_SCALAR &, const FFT_SCALAR &,
const int, FFT_SCALAR * const * const);
void compute_drho1d_thr(FFT_SCALAR * const * const, const FFT_SCALAR &,
const FFT_SCALAR &, const FFT_SCALAR &,
const int, FFT_SCALAR * const * const);
virtual void find_M_thr(int, int &, int &, dbl3_t &);
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Kspace style pppm/tip4p/omp requires newton on
Self-explanatory.
*/