forked from lijiext/lammps
git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8864 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
parent
fb6436ab4e
commit
9a9291036d
|
@ -0,0 +1,51 @@
|
|||
# Install/unInstall package files in LAMMPS
|
||||
# do not install child files if parent does not exist
|
||||
|
||||
for file in *_omp.cpp *_omp.h pppm*proxy.h pppm*proxy.cpp; do
|
||||
# let us see if the "rain man" can count the toothpicks...
|
||||
ofile=`echo $file | sed -e s,_pppm_tip4p_omp,_long_tip4p_omp, \
|
||||
-e s,pppm.\\*_proxy,pppm_omp, -e s,_pppm_omp,_long_omp, \
|
||||
-e s,\\\\\\(.\\*\\\\\\)_omp\\\\.h,\\\\1.h, \
|
||||
-e s,\\\\\\(.\\*\\\\\\)_omp\\\\.cpp,\\\\1.cpp,`
|
||||
if (test $1 = 1) then
|
||||
if (test $file = "thr_omp.h") || (test $file = "thr_omp.cpp") then
|
||||
: # always install those files.
|
||||
elif (test ! -e ../$ofile) then
|
||||
continue
|
||||
fi
|
||||
|
||||
cp $file ..
|
||||
|
||||
elif (test $1 = 0) then
|
||||
rm -f ../$file
|
||||
fi
|
||||
done
|
||||
|
||||
if (test $1 = 1) then
|
||||
|
||||
if (test -e ../Makefile.package) then
|
||||
sed -i -e 's/[^ \t]*OMP[^ \t]* //' ../Makefile.package
|
||||
sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_USER_OMP |' ../Makefile.package
|
||||
fi
|
||||
|
||||
# force rebuild of files with LMP_USER_OMP switch
|
||||
|
||||
touch ../accelerator_omp.h
|
||||
|
||||
cp thr_data.h ..
|
||||
cp thr_data.cpp ..
|
||||
|
||||
elif (test $1 = 0) then
|
||||
|
||||
if (test -e ../Makefile.package) then
|
||||
sed -i -e 's/[^ \t]*OMP[^ \t]* //' ../Makefile.package
|
||||
fi
|
||||
|
||||
# force rebuild of files with LMP_USER_OMP switch
|
||||
|
||||
touch ../accelerator_omp.h
|
||||
|
||||
rm -f ../thr_data.h
|
||||
rm -f ../thr_data.cpp
|
||||
|
||||
fi
|
|
@ -0,0 +1,46 @@
|
|||
# Update package files in LAMMPS
|
||||
# copy package file to src if it doesn't exists or is different
|
||||
# do not copy OpenMP style files, if a non-OpenMP version does
|
||||
# not exist. Do remove OpenMP style files that have no matching
|
||||
# non-OpenMP version installed, e.g. after a package has been
|
||||
# removed
|
||||
for file in *_omp.cpp *_omp.h pppm*proxy.h pppm*proxy.cpp thr_data.h thr_data.cpp; do
|
||||
# let us see if the "rain man" can count the toothpicks...
|
||||
ofile=`echo $file | sed -e s,_pppm_tip4p_omp,_long_tip4p_omp, \
|
||||
-e s,pppm.\\*_proxy,pppm_omp, -e s,_pppm_omp,_long_omp, \
|
||||
-e s,\\\\\\(.\\*\\\\\\)_omp\\\\.\\\\\\(h\\\\\\|cpp\\\\\\),\\\\1.\\\\2,`
|
||||
if (test $file = "thr_omp.h") || (test $file = "thr_omp.cpp") \
|
||||
|| (test $file = "thr_data.h") || (test $file = "thr_data.cpp") then
|
||||
if (test ! -e ../$file) then
|
||||
echo " creating src/$file"
|
||||
cp $file ..
|
||||
elif ! cmp -s $file ../$file ; then
|
||||
echo " updating src/$file"
|
||||
cp $file ..
|
||||
fi
|
||||
elif (test ! -e ../$ofile) then
|
||||
if (test -e ../$file) then
|
||||
echo " removing src/$file"
|
||||
rm -f ../$file
|
||||
fi
|
||||
else
|
||||
if (test ! -e ../$file) then
|
||||
echo " creating src/$file"
|
||||
cp $file ..
|
||||
elif ! cmp -s $file ../$file ; then
|
||||
echo " updating src/$file"
|
||||
cp $file ..
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
for file in thr_data.h thr_data.cpp; do
|
||||
if (test ! -e ../$file) then
|
||||
echo " creating src/$file"
|
||||
cp $file ..
|
||||
elif ! cmp -s $file ../$file ; then
|
||||
echo " updating src/$file"
|
||||
cp $file ..
|
||||
fi
|
||||
done
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
This package provides OpenMP multi-threading support and other
|
||||
optimizations of various LAMMPS pair styles, dihedral styles, and fix
|
||||
styles.
|
||||
|
||||
See this section of the manual to get started:
|
||||
|
||||
doc/Section_accelerate.html, sub-section 5.2
|
||||
|
||||
The person who created this package is Axel Kohlmeyer at Temple U
|
||||
(akohlmey at gmail.com). Contact him directly if you have questions.
|
||||
|
||||
--------------------------
|
||||
|
||||
This directory also contains a shell script:
|
||||
|
||||
hack_openmp_for_pgi.sh
|
||||
|
||||
which will convert OpenMP directives in src files
|
||||
into a form compatible with the PGI compiler.
|
|
@ -0,0 +1,196 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_charmm_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCharmmOMP::AngleCharmmOMP(class LAMMPS *lmp)
|
||||
: AngleCharmm(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCharmmOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCharmmOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double dtheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
|
||||
double delxUB,delyUB,delzUB,rsqUB,rUB,dr,rk,forceUB;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// Urey-Bradley bond
|
||||
|
||||
delxUB = x[i3][0] - x[i1][0];
|
||||
delyUB = x[i3][1] - x[i1][1];
|
||||
delzUB = x[i3][2] - x[i1][2];
|
||||
|
||||
rsqUB = delxUB*delxUB + delyUB*delyUB + delzUB*delzUB;
|
||||
rUB = sqrt(rsqUB);
|
||||
|
||||
// Urey-Bradley force & energy
|
||||
|
||||
dr = rUB - r_ub[type];
|
||||
rk = k_ub[type] * dr;
|
||||
|
||||
if (rUB > 0.0) forceUB = -2.0*rk/rUB;
|
||||
else forceUB = 0.0;
|
||||
|
||||
if (EFLAG) eangle = rk*dr;
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// harmonic force & energy
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
tk = k[type] * dtheta;
|
||||
|
||||
if (EFLAG) eangle += tk*dtheta;
|
||||
|
||||
a = -2.0 * tk * s;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2 - delxUB*forceUB;
|
||||
f1[1] = a11*dely1 + a12*dely2 - delyUB*forceUB;
|
||||
f1[2] = a11*delz1 + a12*delz2 - delzUB*forceUB;
|
||||
|
||||
f3[0] = a22*delx2 + a12*delx1 + delxUB*forceUB;
|
||||
f3[1] = a22*dely2 + a12*dely1 + delyUB*forceUB;
|
||||
f3[2] = a22*delz2 + a12*delz1 + delzUB*forceUB;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(charmm/omp,AngleCharmmOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_CHARMM_OMP_H
|
||||
#define LMP_ANGLE_CHARMM_OMP_H
|
||||
|
||||
#include "angle_charmm.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCharmmOMP : public AngleCharmm, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCharmmOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,240 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_class2_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleClass2OMP::AngleClass2OMP(class LAMMPS *lmp)
|
||||
: AngleClass2(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleClass2OMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleClass2OMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double dtheta,dtheta2,dtheta3,dtheta4,de_angle;
|
||||
double dr1,dr2,tk1,tk2,aa1,aa2,aa11,aa12,aa21,aa22;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22,b1,b2;
|
||||
double vx11,vx12,vy11,vy12,vz11,vz12,vx21,vx22,vy21,vy22,vz21,vz22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// force & energy for angle term
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
dtheta2 = dtheta*dtheta;
|
||||
dtheta3 = dtheta2*dtheta;
|
||||
dtheta4 = dtheta3*dtheta;
|
||||
|
||||
de_angle = 2.0*k2[type]*dtheta + 3.0*k3[type]*dtheta2 +
|
||||
4.0*k4[type]*dtheta3;
|
||||
|
||||
a = -de_angle*s;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
if (EFLAG) eangle = k2[type]*dtheta2 + k3[type]*dtheta3 + k4[type]*dtheta4;
|
||||
|
||||
// force & energy for bond-bond term
|
||||
|
||||
dr1 = r1 - bb_r1[type];
|
||||
dr2 = r2 - bb_r2[type];
|
||||
tk1 = bb_k[type] * dr1;
|
||||
tk2 = bb_k[type] * dr2;
|
||||
|
||||
f1[0] -= delx1*tk2/r1;
|
||||
f1[1] -= dely1*tk2/r1;
|
||||
f1[2] -= delz1*tk2/r1;
|
||||
|
||||
f3[0] -= delx2*tk1/r2;
|
||||
f3[1] -= dely2*tk1/r2;
|
||||
f3[2] -= delz2*tk1/r2;
|
||||
|
||||
if (EFLAG) eangle += bb_k[type]*dr1*dr2;
|
||||
|
||||
// force & energy for bond-angle term
|
||||
|
||||
aa1 = s * dr1 * ba_k1[type];
|
||||
aa2 = s * dr2 * ba_k2[type];
|
||||
|
||||
aa11 = aa1 * c / rsq1;
|
||||
aa12 = -aa1 / (r1 * r2);
|
||||
aa21 = aa2 * c / rsq1;
|
||||
aa22 = -aa2 / (r1 * r2);
|
||||
|
||||
vx11 = (aa11 * delx1) + (aa12 * delx2);
|
||||
vx12 = (aa21 * delx1) + (aa22 * delx2);
|
||||
vy11 = (aa11 * dely1) + (aa12 * dely2);
|
||||
vy12 = (aa21 * dely1) + (aa22 * dely2);
|
||||
vz11 = (aa11 * delz1) + (aa12 * delz2);
|
||||
vz12 = (aa21 * delz1) + (aa22 * delz2);
|
||||
|
||||
aa11 = aa1 * c / rsq2;
|
||||
aa21 = aa2 * c / rsq2;
|
||||
|
||||
vx21 = (aa11 * delx2) + (aa12 * delx1);
|
||||
vx22 = (aa21 * delx2) + (aa22 * delx1);
|
||||
vy21 = (aa11 * dely2) + (aa12 * dely1);
|
||||
vy22 = (aa21 * dely2) + (aa22 * dely1);
|
||||
vz21 = (aa11 * delz2) + (aa12 * delz1);
|
||||
vz22 = (aa21 * delz2) + (aa22 * delz1);
|
||||
|
||||
b1 = ba_k1[type] * dtheta / r1;
|
||||
b2 = ba_k2[type] * dtheta / r2;
|
||||
|
||||
f1[0] -= vx11 + b1*delx1 + vx12;
|
||||
f1[1] -= vy11 + b1*dely1 + vy12;
|
||||
f1[2] -= vz11 + b1*delz1 + vz12;
|
||||
|
||||
f3[0] -= vx21 + b2*delx2 + vx22;
|
||||
f3[1] -= vy21 + b2*dely2 + vy22;
|
||||
f3[2] -= vz21 + b2*delz2 + vz22;
|
||||
|
||||
if (EFLAG) eangle += ba_k1[type]*dr1*dtheta + ba_k2[type]*dr2*dtheta;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(class2/omp,AngleClass2OMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_CLASS2_OMP_H
|
||||
#define LMP_ANGLE_CLASS2_OMP_H
|
||||
|
||||
#include "angle_class2.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleClass2OMP : public AngleClass2, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleClass2OMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,189 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_delta_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineDeltaOMP::AngleCosineDeltaOMP(class LAMMPS *lmp)
|
||||
: AngleCosineDelta(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineDeltaOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosineDeltaOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,theta,dtheta,dcostheta,tk;
|
||||
double eangle,f1[3],f3[3];
|
||||
double rsq1,rsq2,r1,r2,c,a,cot,a11,a12,a22,b11,b12,b22,c0,s0,s;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
theta = acos(c);
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
cot = c/s;
|
||||
|
||||
// force & energy
|
||||
|
||||
dtheta = theta - theta0[type];
|
||||
dcostheta = cos(dtheta);
|
||||
tk = k[type] * (1.0-dcostheta);
|
||||
|
||||
if (EFLAG) eangle = tk;
|
||||
|
||||
a = -k[type];
|
||||
|
||||
// expand dtheta for cos and sin contribution to force
|
||||
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
b11 = -a*c*cot / rsq1;
|
||||
b12 = a*cot / (r1*r2);
|
||||
b22 = -a*c*cot / rsq2;
|
||||
|
||||
c0 = cos(theta0[type]);
|
||||
s0 = sin(theta0[type]);
|
||||
|
||||
f1[0] = (a11*delx1 + a12*delx2)*c0 + (b11*delx1 + b12*delx2)*s0;
|
||||
f1[1] = (a11*dely1 + a12*dely2)*c0 + (b11*dely1 + b12*dely2)*s0;
|
||||
f1[2] = (a11*delz1 + a12*delz2)*c0 + (b11*delz1 + b12*delz2)*s0;
|
||||
f3[0] = (a22*delx2 + a12*delx1)*c0 + (b22*delx2 + b12*delx1)*s0;
|
||||
f3[1] = (a22*dely2 + a12*dely1)*c0 + (b22*dely2 + b12*dely1)*s0;
|
||||
f3[2] = (a22*delz2 + a12*delz1)*c0 + (b22*delz2 + b12*delz1)*s0;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/delta/omp,AngleCosineDeltaOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_DELTA_OMP_H
|
||||
#define LMP_ANGLE_COSINE_DELTA_OMP_H
|
||||
|
||||
#include "angle_cosine_delta.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosineDeltaOMP : public AngleCosineDelta, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosineDeltaOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,166 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineOMP::AngleCosineOMP(class LAMMPS *lmp)
|
||||
: AngleCosine(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosineOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (EFLAG) eangle = k[type]*(1.0+c);
|
||||
|
||||
a = k[type];
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/omp,AngleCosineOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_OMP_H
|
||||
#define LMP_ANGLE_COSINE_OMP_H
|
||||
|
||||
#include "angle_cosine.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosineOMP : public AngleCosine, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosineOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,204 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_periodic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosinePeriodicOMP::AngleCosinePeriodicOMP(class LAMMPS *lmp)
|
||||
: AngleCosinePeriodic(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosinePeriodicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosinePeriodicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i,i1,i2,i3,n,m,type,b_factor;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
|
||||
double tn,tn_1,tn_2,un,un_1,un_2;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
m = multiplicity[type];
|
||||
b_factor = b[type];
|
||||
|
||||
// cos(n*x) = Tn(cos(x))
|
||||
// Tn(x) = Chebyshev polynomials of the first kind: T_0 = 1, T_1 = x, ...
|
||||
// recurrence relationship:
|
||||
// Tn(x) = 2*x*T[n-1](x) - T[n-2](x) where T[-1](x) = 0
|
||||
// also, dTn(x)/dx = n*U[n-1](x)
|
||||
// where Un(x) = 2*x*U[n-1](x) - U[n-2](x) and U[-1](x) = 0
|
||||
// finally need to handle special case for n = 1
|
||||
|
||||
tn = 1.0;
|
||||
tn_1 = 1.0;
|
||||
tn_2 = 0.0;
|
||||
un = 1.0;
|
||||
un_1 = 2.0;
|
||||
un_2 = 0.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// force & energy
|
||||
|
||||
tn_2 = c;
|
||||
for (i = 1; i <= m; i++) {
|
||||
tn = 2*c*tn_1 - tn_2;
|
||||
tn_2 = tn_1;
|
||||
tn_1 = tn;
|
||||
}
|
||||
|
||||
for (i = 2; i <= m; i++) {
|
||||
un = 2*c*un_1 - un_2;
|
||||
un_2 = un_1;
|
||||
un_1 = un;
|
||||
}
|
||||
tn = b_factor*pow(-1.0,(double)m)*tn;
|
||||
un = b_factor*pow(-1.0,(double)m)*m*un;
|
||||
|
||||
if (EFLAG) eangle = 2*k[type]*(1.0 - tn);
|
||||
|
||||
a = -k[type]*un;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/periodic/omp,AngleCosinePeriodicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_PERIODIC_OMP_H
|
||||
#define LMP_ANGLE_COSINE_PERIODIC_OMP_H
|
||||
|
||||
#include "angle_cosine_periodic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosinePeriodicOMP : public AngleCosinePeriodic, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosinePeriodicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,187 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_shift_exp_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineShiftExpOMP::AngleCosineShiftExpOMP(class LAMMPS *lmp)
|
||||
: AngleCosineShiftExp(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineShiftExpOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosineShiftExpOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3],ff;
|
||||
double rsq1,rsq2,r1,r2,c,s,a11,a12,a22;
|
||||
double exp2,aa,uumin,cccpsss,cssmscc;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// C= sine of angle
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
|
||||
// force & energy
|
||||
|
||||
aa=a[type];
|
||||
uumin=umin[type];
|
||||
|
||||
cccpsss = c*cost[type]+s*sint[type];
|
||||
cssmscc = c*sint[type]-s*cost[type];
|
||||
|
||||
if (doExpansion[type])
|
||||
{ // |a|<0.01 so use expansions relative precision <1e-5
|
||||
// std::cout << "Using expansion\n";
|
||||
if (EFLAG) eangle = -0.125*(1+cccpsss)*(4+aa*(cccpsss-1))*uumin;
|
||||
ff=0.25*uumin*cssmscc*(2+aa*cccpsss)/s;
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cout << "Not using expansion\n";
|
||||
exp2=exp(0.5*aa*(1+cccpsss));
|
||||
if (EFLAG) eangle = opt1[type]*(1-exp2);
|
||||
ff=0.5*a[type]*opt1[type]*exp2*cssmscc/s;
|
||||
}
|
||||
|
||||
a11 = ff*c/ rsq1;
|
||||
a12 = -ff / (r1*r2);
|
||||
a22 = ff*c/ rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/shift/exp/omp,AngleCosineShiftExpOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_SHIFT_EXP_OMP_H
|
||||
#define LMP_ANGLE_COSINE_SHIFT_EXP_OMP_H
|
||||
|
||||
#include "angle_cosine_shift_exp.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosineShiftExpOMP : public AngleCosineShiftExp, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosineShiftExpOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_shift_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineShiftOMP::AngleCosineShiftOMP(class LAMMPS *lmp)
|
||||
: AngleCosineShift(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineShiftOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosineShiftOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double f1[3],f3[3];
|
||||
double rsq1,rsq2,r1,r2,c,s,cps,a11,a12,a22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
double eangle = 0.0;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// c = cosine of angle
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// C= sine of angle
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
|
||||
// force & energy
|
||||
const double kcos=kcost[type];
|
||||
const double ksin=ksint[type];
|
||||
if (EFLAG) eangle = -k[type]-kcos*c-ksin*s;
|
||||
|
||||
cps = c/s; // NOTE absorbed one c
|
||||
|
||||
a11 = (-kcos +ksin*cps )*c/ rsq1;
|
||||
a12 = ( kcos -ksin*cps ) / (r1*r2);
|
||||
a22 = (-kcos +ksin*cps )*c/ rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/shift/omp,AngleCosineShiftOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_SHIFT_OMP_H
|
||||
#define LMP_ANGLE_COSINE_SHIFT_OMP_H
|
||||
|
||||
#include "angle_cosine_shift.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosineShiftOMP : public AngleCosineShift, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosineShiftOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,171 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_cosine_squared_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleCosineSquaredOMP::AngleCosineSquaredOMP(class LAMMPS *lmp)
|
||||
: AngleCosineSquared(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleCosineSquaredOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleCosineSquaredOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double dcostheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
|
||||
dcostheta = c - cos(theta0[type]);
|
||||
tk = k[type] * dcostheta;
|
||||
|
||||
if (EFLAG) eangle = tk*dcostheta;
|
||||
|
||||
a = 2.0 * tk;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(cosine/squared/omp,AngleCosineSquaredOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_COSINE_SQUARED_OMP_H
|
||||
#define LMP_ANGLE_COSINE_SQUARED_OMP_H
|
||||
|
||||
#include "angle_cosine_squared.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleCosineSquaredOMP : public AngleCosineSquared, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleCosineSquaredOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_dipole_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleDipoleOMP::AngleDipoleOMP(class LAMMPS *lmp)
|
||||
: AngleDipole(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleDipoleOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
if (!force->newton_bond)
|
||||
error->all(FLERR,"'newton' flag for bonded interactions must be 'on'");
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (eflag)
|
||||
eval<1>(ifrom, ito, thr);
|
||||
else
|
||||
eval<0>(ifrom, ito, thr);
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
|
||||
}
|
||||
|
||||
template <int EFLAG>
|
||||
void AngleDipoleOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int iRef,iDip,iDummy,n,type;
|
||||
double delx,dely,delz;
|
||||
double eangle,tangle;
|
||||
double r,cosGamma,deltaGamma,kdg,rmu;
|
||||
|
||||
const double * const * const x = atom->x; // position vector
|
||||
const double * const * const mu = atom->mu; // point-dipole components and moment magnitude
|
||||
double * const * const torque = thr->get_torque();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
const double f1[3] = {0.0, 0.0, 0.0};
|
||||
const double f3[3] = {0.0, 0.0, 0.0};
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
iDip = anglelist[n][0]; // dipole whose orientation is to be restrained
|
||||
iRef = anglelist[n][1]; // reference atom toward which dipole will point
|
||||
iDummy = anglelist[n][2]; // dummy atom - irrelevant to the interaction
|
||||
type = anglelist[n][3];
|
||||
|
||||
delx = x[iRef][0] - x[iDip][0];
|
||||
dely = x[iRef][1] - x[iDip][1];
|
||||
delz = x[iRef][2] - x[iDip][2];
|
||||
|
||||
r = sqrt(delx*delx + dely*dely + delz*delz);
|
||||
|
||||
rmu = r * mu[iDip][3];
|
||||
cosGamma = (mu[iDip][0]*delx+mu[iDip][1]*dely+mu[iDip][2]*delz) / rmu;
|
||||
deltaGamma = cosGamma - cos(gamma0[type]);
|
||||
kdg = k[type] * deltaGamma;
|
||||
|
||||
if (EFLAG) eangle = kdg * deltaGamma; // energy
|
||||
|
||||
tangle = 2.0 * kdg / rmu;
|
||||
|
||||
torque[iDip][0] += tangle * (dely*mu[iDip][2] - delz*mu[iDip][1]);
|
||||
torque[iDip][1] += tangle * (delz*mu[iDip][0] - delx*mu[iDip][2]);
|
||||
torque[iDip][2] += tangle * (delx*mu[iDip][1] - dely*mu[iDip][0]);
|
||||
|
||||
if (EFLAG) // tally energy (virial=0 because force=0)
|
||||
ev_tally_thr(this,iRef,iDip,iDummy,nlocal,/* NEWTON_BOND */ 1,
|
||||
eangle,f1,f3,0.0,0.0,0.0,0.0,0.0,0.0,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(dipole/omp,AngleDipoleOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_DIPOLE_OMP_H
|
||||
#define LMP_ANGLE_DIPOLE_OMP_H
|
||||
|
||||
#include "angle_dipole.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleDipoleOMP : public AngleDipole, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleDipoleOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EFLAG>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,175 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_harmonic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleHarmonicOMP::AngleHarmonicOMP(class LAMMPS *lmp)
|
||||
: AngleHarmonic(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleHarmonicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleHarmonicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double eangle,f1[3],f3[3];
|
||||
double dtheta,tk;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// force & energy
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
tk = k[type] * dtheta;
|
||||
|
||||
if (EFLAG) eangle = tk*dtheta;
|
||||
|
||||
a = -2.0 * tk * s;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(harmonic/omp,AngleHarmonicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_HARMONIC_OMP_H
|
||||
#define LMP_ANGLE_HARMONIC_OMP_H
|
||||
|
||||
#include "angle_harmonic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleHarmonicOMP : public AngleHarmonic, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleHarmonicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,230 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_sdk_omp.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "lj_sdk_common.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
using namespace LJSDKParms;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleSDKOMP::AngleSDKOMP(class LAMMPS *lmp)
|
||||
: AngleSDK(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleSDKOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleSDKOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2,delx3,dely3,delz3;
|
||||
double eangle,f1[3],f3[3],e13,f13;
|
||||
double dtheta,tk;
|
||||
double rsq1,rsq2,rsq3,r1,r2,c,s,a,a11,a12,a22;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// 1-3 LJ interaction.
|
||||
// we only want to use the repulsive part,
|
||||
// and it can be scaled (or off).
|
||||
// so this has to be done here and not in the
|
||||
// general non-bonded code.
|
||||
|
||||
f13 = e13 = delx3 = dely3 = delz3 = 0.0;
|
||||
|
||||
if (repflag) {
|
||||
|
||||
delx3 = x[i1][0] - x[i3][0];
|
||||
dely3 = x[i1][1] - x[i3][1];
|
||||
delz3 = x[i1][2] - x[i3][2];
|
||||
rsq3 = delx3*delx3 + dely3*dely3 + delz3*delz3;
|
||||
|
||||
const int type1 = atom->type[i1];
|
||||
const int type3 = atom->type[i3];
|
||||
|
||||
if (rsq3 < rminsq[type1][type3]) {
|
||||
const int ljt = lj_type[type1][type3];
|
||||
const double r2inv = 1.0/rsq3;
|
||||
|
||||
if (ljt == LJ12_4) {
|
||||
const double r4inv=r2inv*r2inv;
|
||||
|
||||
f13 = r4inv*(lj1[type1][type3]*r4inv*r4inv - lj2[type1][type3]);
|
||||
if (EFLAG) e13 = r4inv*(lj3[type1][type3]*r4inv*r4inv - lj4[type1][type3]);
|
||||
|
||||
} else if (ljt == LJ9_6) {
|
||||
const double r3inv = r2inv*sqrt(r2inv);
|
||||
const double r6inv = r3inv*r3inv;
|
||||
|
||||
f13 = r6inv*(lj1[type1][type3]*r3inv - lj2[type1][type3]);
|
||||
if (EFLAG) e13 = r6inv*(lj3[type1][type3]*r3inv - lj4[type1][type3]);
|
||||
|
||||
} else if (ljt == LJ12_6) {
|
||||
const double r6inv = r2inv*r2inv*r2inv;
|
||||
|
||||
f13 = r6inv*(lj1[type1][type3]*r6inv - lj2[type1][type3]);
|
||||
if (EFLAG) e13 = r6inv*(lj3[type1][type3]*r6inv - lj4[type1][type3]);
|
||||
}
|
||||
|
||||
// make sure energy is 0.0 at the cutoff.
|
||||
if (EFLAG) e13 -= emin[type1][type3];
|
||||
|
||||
f13 *= r2inv;
|
||||
}
|
||||
}
|
||||
|
||||
// force & energy
|
||||
|
||||
dtheta = acos(c) - theta0[type];
|
||||
tk = k[type] * dtheta;
|
||||
|
||||
if (EFLAG) eangle = tk*dtheta;
|
||||
|
||||
a = -2.0 * tk * s;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of the 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0] + f13*delx3;
|
||||
f[i1][1] += f1[1] + f13*dely3;
|
||||
f[i1][2] += f1[2] + f13*delz3;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0] - f13*delx3;
|
||||
f[i3][1] += f3[1] - f13*dely3;
|
||||
f[i3][2] += f3[2] - f13*delz3;
|
||||
}
|
||||
|
||||
if (EVFLAG) {
|
||||
ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
if (repflag) ev_tally13_thr(this,i1,i3,nlocal,NEWTON_BOND,
|
||||
e13,f13,delx3,dely3,delz3,thr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(sdk/omp,AngleSDKOMP)
|
||||
AngleStyle(cg/cmm/omp,AngleSDKOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_SDK_OMP_H
|
||||
#define LMP_ANGLE_SDK_OMP_H
|
||||
|
||||
#include "angle_sdk.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleSDKOMP : public AngleSDK, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleSDKOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,175 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "angle_table_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AngleTableOMP::AngleTableOMP(class LAMMPS *lmp)
|
||||
: AngleTable(lmp), ThrOMP(lmp,THR_ANGLE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AngleTableOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nanglelist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void AngleTableOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,n,type;
|
||||
double eangle,f1[3],f3[3];
|
||||
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
|
||||
double theta,u,mdu; //mdu: minus du, -du/dx=f
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const anglelist = neighbor->anglelist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = anglelist[n][0];
|
||||
i2 = anglelist[n][1];
|
||||
i3 = anglelist[n][2];
|
||||
type = anglelist[n][3];
|
||||
|
||||
// 1st bond
|
||||
|
||||
delx1 = x[i1][0] - x[i2][0];
|
||||
dely1 = x[i1][1] - x[i2][1];
|
||||
delz1 = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||
r1 = sqrt(rsq1);
|
||||
|
||||
// 2nd bond
|
||||
|
||||
delx2 = x[i3][0] - x[i2][0];
|
||||
dely2 = x[i3][1] - x[i2][1];
|
||||
delz2 = x[i3][2] - x[i2][2];
|
||||
|
||||
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||
r2 = sqrt(rsq2);
|
||||
|
||||
// angle (cos and sin)
|
||||
|
||||
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||
c /= r1*r2;
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
s = 1.0/s;
|
||||
|
||||
// tabulated force & energy
|
||||
|
||||
theta = acos(c);
|
||||
uf_lookup(type,theta,u,mdu);
|
||||
|
||||
if (EFLAG) eangle = u;
|
||||
|
||||
a = mdu * s;
|
||||
a11 = a*c / rsq1;
|
||||
a12 = -a / (r1*r2);
|
||||
a22 = a*c / rsq2;
|
||||
|
||||
f1[0] = a11*delx1 + a12*delx2;
|
||||
f1[1] = a11*dely1 + a12*dely2;
|
||||
f1[2] = a11*delz1 + a12*delz2;
|
||||
f3[0] = a22*delx2 + a12*delx1;
|
||||
f3[1] = a22*dely2 + a12*dely1;
|
||||
f3[2] = a22*delz2 + a12*delz1;
|
||||
|
||||
// apply force to each of 3 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= f1[0] + f3[0];
|
||||
f[i2][1] -= f1[1] + f3[1];
|
||||
f[i2][2] -= f1[2] + f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,i3,nlocal,NEWTON_BOND,eangle,f1,f3,
|
||||
delx1,dely1,delz1,delx2,dely2,delz2,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ANGLE_CLASS
|
||||
|
||||
AngleStyle(table/omp,AngleTableOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ANGLE_TABLE_OMP_H
|
||||
#define LMP_ANGLE_TABLE_OMP_H
|
||||
|
||||
#include "angle_table.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AngleTableOMP : public AngleTable, public ThrOMP {
|
||||
|
||||
public:
|
||||
AngleTableOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,132 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_class2_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondClass2OMP::BondClass2OMP(class LAMMPS *lmp)
|
||||
: BondClass2(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondClass2OMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondClass2OMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,dr2,dr3,dr4,de_bond;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
dr2 = dr*dr;
|
||||
dr3 = dr2*dr;
|
||||
dr4 = dr3*dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
de_bond = 2.0*k2[type]*dr + 3.0*k3[type]*dr2 + 4.0*k4[type]*dr3;
|
||||
if (r > 0.0) fbond = -de_bond/r;
|
||||
else fbond = 0.0;
|
||||
|
||||
if (EFLAG) ebond = k2[type]*dr2 + k3[type]*dr3 + k4[type]*dr4;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(class2/omp,BondClass2OMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_CLASS2_OMP_H
|
||||
#define LMP_BOND_CLASS2_OMP_H
|
||||
|
||||
#include "bond_class2.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondClass2OMP : public BondClass2, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondClass2OMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,162 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_fene_expand_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondFENEExpandOMP::BondFENEExpandOMP(class LAMMPS *lmp)
|
||||
: BondFENEExpand(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEExpandOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondFENEExpandOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r0sq,rlogarg,sr2,sr6;
|
||||
double r,rshift,rshiftsq;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
const int tid = thr->get_tid();
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
rshift = r - shift[type];
|
||||
rshiftsq = rshift*rshift;
|
||||
r0sq = r0[type] * r0[type];
|
||||
rlogarg = 1.0 - rshiftsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
|
||||
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %d %d %g",
|
||||
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
|
||||
error->warning(FLERR,str,0);
|
||||
|
||||
if (check_error_thr((rlogarg <= -3.0),tid,FLERR,"Bad FENE bond"))
|
||||
return;
|
||||
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fbond = -k[type]*rshift/rlogarg/r;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rshiftsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fbond += 48.0*epsilon[type]*sr6*(sr6-0.5)/rshift/r;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (EFLAG) {
|
||||
ebond = -0.5 * k[type]*r0sq*log(rlogarg);
|
||||
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
ebond += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
|
||||
}
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(fene/expand/omp,BondFENEExpandOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_FENE_EXPAND_OMP_H
|
||||
#define LMP_BOND_FENE_EXPAND_OMP_H
|
||||
|
||||
#include "bond_fene_expand.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondFENEExpandOMP : public BondFENEExpand, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondFENEExpandOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,158 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_fene_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
#include "update.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondFENEOMP::BondFENEOMP(class LAMMPS *lmp)
|
||||
: BondFENE(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondFENEOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondFENEOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r0sq,rlogarg,sr2,sr6;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
const int tid = thr->get_tid();
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r0sq = r0[type] * r0[type];
|
||||
rlogarg = 1.0 - rsq/r0sq;
|
||||
|
||||
// if r -> r0, then rlogarg < 0.0 which is an error
|
||||
// issue a warning and reset rlogarg = epsilon
|
||||
// if r > 2*r0 something serious is wrong, abort
|
||||
|
||||
if (rlogarg < 0.1) {
|
||||
char str[128];
|
||||
|
||||
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %d %d %g",
|
||||
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
|
||||
error->warning(FLERR,str,0);
|
||||
|
||||
if (check_error_thr((rlogarg <= -3.0),tid,FLERR,"Bad FENE bond"))
|
||||
return;
|
||||
|
||||
rlogarg = 0.1;
|
||||
}
|
||||
|
||||
fbond = -k[type]/rlogarg;
|
||||
|
||||
// force from LJ term
|
||||
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type]) {
|
||||
sr2 = sigma[type]*sigma[type]/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fbond += 48.0*epsilon[type]*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
// energy
|
||||
|
||||
if (EFLAG) {
|
||||
ebond = -0.5 * k[type]*r0sq*log(rlogarg);
|
||||
if (rsq < TWO_1_3*sigma[type]*sigma[type])
|
||||
ebond += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
|
||||
}
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(fene/omp,BondFENEOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_FENE_OMP_H
|
||||
#define LMP_BOND_FENE_OMP_H
|
||||
|
||||
#include "bond_fene.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondFENEOMP : public BondFENE, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondFENEOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_harmonic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondHarmonicOMP::BondHarmonicOMP(class LAMMPS *lmp)
|
||||
: BondHarmonic(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondHarmonicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,rk;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
rk = k[type] * dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fbond = -2.0*rk/r;
|
||||
else fbond = 0.0;
|
||||
|
||||
if (EFLAG) ebond = rk*dr;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(harmonic/omp,BondHarmonicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_HARMONIC_OMP_H
|
||||
#define LMP_BOND_HARMONIC_OMP_H
|
||||
|
||||
#include "bond_harmonic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondHarmonicOMP : public BondHarmonic, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondHarmonicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,132 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_harmonic_shift_cut_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondHarmonicShiftCutOMP::BondHarmonicShiftCutOMP(class LAMMPS *lmp)
|
||||
: BondHarmonicShiftCut(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonicShiftCutOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondHarmonicShiftCutOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,rk;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
|
||||
if (r>r1[type]) continue;
|
||||
|
||||
dr = r - r0[type];
|
||||
rk = k[type] * dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fbond = -2.0*rk/r;
|
||||
else fbond = 0.0;
|
||||
|
||||
if (EFLAG)
|
||||
ebond = k[type]*(dr*dr -(r0[type]-r1[type])*(r0[type]-r1[type]) );
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(harmonic/shift/cut/omp,BondHarmonicShiftCutOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_HARMONIC_SHIFT_CUT_OMP_H
|
||||
#define LMP_BOND_HARMONIC_SHIFT_CUT_OMP_H
|
||||
|
||||
#include "bond_harmonic_shift_cut.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondHarmonicShiftCutOMP : public BondHarmonicShiftCut, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondHarmonicShiftCutOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,129 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_harmonic_shift_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondHarmonicShiftOMP::BondHarmonicShiftOMP(class LAMMPS *lmp)
|
||||
: BondHarmonicShift(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondHarmonicShiftOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondHarmonicShiftOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,rk;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
rk = k[type] * dr;
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fbond = -2.0*rk/r;
|
||||
else fbond = 0.0;
|
||||
|
||||
if (EFLAG)
|
||||
ebond = k[type]*(dr*dr -(r0[type]-r1[type])*(r0[type]-r1[type]) );
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(harmonic/shift/omp,BondHarmonicShiftOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_HARMONIC_SHIFT_OMP_H
|
||||
#define LMP_BOND_HARMONIC_SHIFT_OMP_H
|
||||
|
||||
#include "bond_harmonic_shift.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondHarmonicShiftOMP : public BondHarmonicShift, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondHarmonicShiftOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,129 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_morse_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondMorseOMP::BondMorseOMP(class LAMMPS *lmp)
|
||||
: BondMorse(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondMorseOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondMorseOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,ralpha;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
|
||||
dr = r - r0[type];
|
||||
ralpha = exp(-alpha[type]*dr);
|
||||
|
||||
// force & energy
|
||||
|
||||
if (r > 0.0) fbond = -2.0*d0[type]*alpha[type]*(1-ralpha)*ralpha/r;
|
||||
else fbond = 0.0;
|
||||
|
||||
if (EFLAG) ebond = d0[type]*(1-ralpha)*(1-ralpha);
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(morse/omp,BondMorseOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_MORSE_OMP_H
|
||||
#define LMP_BOND_MORSE_OMP_H
|
||||
|
||||
#include "bond_morse.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondMorseOMP : public BondMorse, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondMorseOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,129 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_nonlinear_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondNonlinearOMP::BondNonlinearOMP(class LAMMPS *lmp)
|
||||
: BondNonlinear(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondNonlinearOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondNonlinearOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r,dr,drsq,lamdasq,denom,denomsq;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
dr = r - r0[type];
|
||||
drsq = dr*dr;
|
||||
lamdasq = lamda[type]*lamda[type];
|
||||
denom = lamdasq - drsq;
|
||||
denomsq = denom*denom;
|
||||
|
||||
// force & energy
|
||||
|
||||
fbond = -epsilon[type]/r * 2.0*dr*lamdasq/denomsq;
|
||||
if (EFLAG) ebond = epsilon[type] * drsq / denom;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(nonlinear/omp,BondNonlinearOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_NONLINEAR_OMP_H
|
||||
#define LMP_BOND_NONLINEAR_OMP_H
|
||||
|
||||
#include "bond_nonlinear.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondNonlinearOMP : public BondNonlinear, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondNonlinearOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,197 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_quartic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "pair.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondQuarticOMP::BondQuarticOMP(class LAMMPS *lmp)
|
||||
: BondQuartic(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondQuarticOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
// insure pair->ev_tally() will use 1-4 virial contribution
|
||||
|
||||
if (vflag_global == 2)
|
||||
force->pair->vflag_either = force->pair->vflag_global = 1;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondQuarticOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,m,type,itype,jtype;
|
||||
double delx,dely,delz,ebond,fbond,evdwl,fpair;
|
||||
double r,rsq,dr,r2,ra,rb,sr2,sr6;
|
||||
|
||||
ebond = evdwl = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
int * const * const bondlist = neighbor->bondlist;
|
||||
const double * const * const cutsq = force->pair->cutsq;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
|
||||
// skip bond if already broken
|
||||
|
||||
if (bondlist[n][2] <= 0) continue;
|
||||
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
// if bond breaks, set type to 0
|
||||
// both in temporary bondlist and permanent bond_type
|
||||
// if this proc owns both atoms,
|
||||
// negate bond_type twice if other atom stores it
|
||||
// if other proc owns 2nd atom, other proc will also break bond
|
||||
|
||||
if (rsq > rc[type]*rc[type]) {
|
||||
bondlist[n][2] = 0;
|
||||
for (m = 0; m < atom->num_bond[i1]; m++)
|
||||
if (atom->bond_atom[i1][m] == atom->tag[i2])
|
||||
atom->bond_type[i1][m] = 0;
|
||||
if (i2 < atom->nlocal)
|
||||
for (m = 0; m < atom->num_bond[i2]; m++)
|
||||
if (atom->bond_atom[i2][m] == atom->tag[i1])
|
||||
atom->bond_type[i2][m] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// quartic bond
|
||||
// 1st portion is from quartic term
|
||||
// 2nd portion is from LJ term cut at 2^(1/6) with eps = sigma = 1.0
|
||||
|
||||
r = sqrt(rsq);
|
||||
dr = r - rc[type];
|
||||
r2 = dr*dr;
|
||||
ra = dr - b1[type];
|
||||
rb = dr - b2[type];
|
||||
fbond = -k[type]/r * (r2*(ra+rb) + 2.0*dr*ra*rb);
|
||||
|
||||
if (rsq < TWO_1_3) {
|
||||
sr2 = 1.0/rsq;
|
||||
sr6 = sr2*sr2*sr2;
|
||||
fbond += 48.0*sr6*(sr6-0.5)/rsq;
|
||||
}
|
||||
|
||||
if (EFLAG) {
|
||||
ebond = k[type]*r2*ra*rb + u0[type];
|
||||
if (rsq < TWO_1_3) ebond += 4.0*sr6*(sr6-1.0) + 1.0;
|
||||
}
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,ebond,fbond,delx,dely,delz,thr);
|
||||
|
||||
// subtract out pairwise contribution from 2 atoms via pair->single()
|
||||
// required since special_bond = 1,1,1
|
||||
// tally energy/virial in pair, using newton_bond as newton flag
|
||||
|
||||
itype = atom->type[i1];
|
||||
jtype = atom->type[i2];
|
||||
|
||||
if (rsq < cutsq[itype][jtype]) {
|
||||
evdwl = -force->pair->single(i1,i2,itype,jtype,rsq,1.0,1.0,fpair);
|
||||
fpair = -fpair;
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fpair;
|
||||
f[i1][1] += dely*fpair;
|
||||
f[i1][2] += delz*fpair;
|
||||
}
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fpair;
|
||||
f[i2][1] -= dely*fpair;
|
||||
f[i2][2] -= delz*fpair;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(force->pair,i1,i2,nlocal,NEWTON_BOND,
|
||||
evdwl,0.0,fpair,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(quartic/omp,BondQuarticOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_QUARTIC_OMP_H
|
||||
#define LMP_BOND_QUARTIC_OMP_H
|
||||
|
||||
#include "bond_quartic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondQuarticOMP : public BondQuartic, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondQuarticOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,126 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "bond_table_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BondTableOMP::BondTableOMP(class LAMMPS *lmp)
|
||||
: BondTable(lmp), ThrOMP(lmp,THR_BOND)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void BondTableOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nbondlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void BondTableOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,n,type;
|
||||
double delx,dely,delz,ebond,fbond;
|
||||
double rsq,r;
|
||||
double u,mdu;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const bondlist = neighbor->bondlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = bondlist[n][0];
|
||||
i2 = bondlist[n][1];
|
||||
type = bondlist[n][2];
|
||||
|
||||
delx = x[i1][0] - x[i2][0];
|
||||
dely = x[i1][1] - x[i2][1];
|
||||
delz = x[i1][2] - x[i2][2];
|
||||
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r = sqrt(rsq);
|
||||
|
||||
// force & energy
|
||||
|
||||
uf_lookup(type,r,u,mdu);
|
||||
fbond = mdu/r;
|
||||
ebond = u;
|
||||
|
||||
// apply force to each of 2 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fbond;
|
||||
f[i1][1] += dely*fbond;
|
||||
f[i1][2] += delz*fbond;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] -= delx*fbond;
|
||||
f[i2][1] -= dely*fbond;
|
||||
f[i2][2] -= delz*fbond;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(this,i1,i2,nlocal,NEWTON_BOND,
|
||||
ebond,fbond,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef BOND_CLASS
|
||||
|
||||
BondStyle(table/omp,BondTableOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_BOND_TABLE_OMP_H
|
||||
#define LMP_BOND_TABLE_OMP_H
|
||||
|
||||
#include "bond_table.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class BondTableOMP : public BondTable, public ThrOMP {
|
||||
|
||||
public:
|
||||
BondTableOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,322 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "lmptype.h"
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "dihedral_charmm_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralCharmmOMP::DihedralCharmmOMP(class LAMMPS *lmp)
|
||||
: DihedralCharmm(lmp), ThrOMP(lmp,THR_DIHEDRAL|THR_CHARMM)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCharmmOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
// insure pair->ev_tally() will use 1-4 virial contribution
|
||||
|
||||
if (weightflag && vflag_global == 2)
|
||||
force->pair->vflag_either = force->pair->vflag_global = 1;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralCharmmOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,i,m,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
|
||||
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
|
||||
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
|
||||
double c,s,p,sx2,sy2,sz2;
|
||||
int itype,jtype;
|
||||
double delx,dely,delz,rsq,r2inv,r6inv;
|
||||
double forcecoul,forcelj,fpair,ecoul,evdwl;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const double * const q = atom->q;
|
||||
const int * const atomtype = atom->type;
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const double qqrd2e = force->qqrd2e;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c,s calculation
|
||||
|
||||
ax = vb1y*vb2zm - vb1z*vb2ym;
|
||||
ay = vb1z*vb2xm - vb1x*vb2zm;
|
||||
az = vb1x*vb2ym - vb1y*vb2xm;
|
||||
bx = vb3y*vb2zm - vb3z*vb2ym;
|
||||
by = vb3z*vb2xm - vb3x*vb2zm;
|
||||
bz = vb3x*vb2ym - vb3y*vb2xm;
|
||||
|
||||
rasq = ax*ax + ay*ay + az*az;
|
||||
rbsq = bx*bx + by*by + bz*bz;
|
||||
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
|
||||
rg = sqrt(rgsq);
|
||||
|
||||
rginv = ra2inv = rb2inv = 0.0;
|
||||
if (rg > 0) rginv = 1.0/rg;
|
||||
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||
rabinv = sqrt(ra2inv*rb2inv);
|
||||
|
||||
c = (ax*bx + ay*by + az*bz)*rabinv;
|
||||
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
m = multiplicity[type];
|
||||
p = 1.0;
|
||||
ddf1 = df1 = 0.0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
ddf1 = p*c - df1*s;
|
||||
df1 = p*s + df1*c;
|
||||
p = ddf1;
|
||||
}
|
||||
|
||||
p = p*cos_shift[type] + df1*sin_shift[type];
|
||||
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
|
||||
df1 *= -m;
|
||||
p += 1.0;
|
||||
|
||||
if (m == 0) {
|
||||
p = 1.0 + cos_shift[type];
|
||||
df1 = 0.0;
|
||||
}
|
||||
|
||||
if (EFLAG) edihedral = k[type] * p;
|
||||
|
||||
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
|
||||
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
|
||||
fga = fg*ra2inv*rginv;
|
||||
hgb = hg*rb2inv*rginv;
|
||||
gaa = -ra2inv*rg;
|
||||
gbb = rb2inv*rg;
|
||||
|
||||
dtfx = gaa*ax;
|
||||
dtfy = gaa*ay;
|
||||
dtfz = gaa*az;
|
||||
dtgx = fga*ax - hgb*bx;
|
||||
dtgy = fga*ay - hgb*by;
|
||||
dtgz = fga*az - hgb*bz;
|
||||
dthx = gbb*bx;
|
||||
dthy = gbb*by;
|
||||
dthz = gbb*bz;
|
||||
|
||||
df = -k[type] * df1;
|
||||
|
||||
sx2 = df*dtgx;
|
||||
sy2 = df*dtgy;
|
||||
sz2 = df*dtgz;
|
||||
|
||||
f1[0] = df*dtfx;
|
||||
f1[1] = df*dtfy;
|
||||
f1[2] = df*dtfz;
|
||||
|
||||
f2[0] = sx2 - f1[0];
|
||||
f2[1] = sy2 - f1[1];
|
||||
f2[2] = sz2 - f1[2];
|
||||
|
||||
f4[0] = df*dthx;
|
||||
f4[1] = df*dthy;
|
||||
f4[2] = df*dthz;
|
||||
|
||||
f3[0] = -sx2 - f4[0];
|
||||
f3[1] = -sy2 - f4[1];
|
||||
f3[2] = -sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
// 1-4 LJ and Coulomb interactions
|
||||
// tally energy/virial in pair, using newton_bond as newton flag
|
||||
|
||||
if (weight[type] > 0.0) {
|
||||
itype = atomtype[i1];
|
||||
jtype = atomtype[i4];
|
||||
|
||||
delx = x[i1][0] - x[i4][0];
|
||||
dely = x[i1][1] - x[i4][1];
|
||||
delz = x[i1][2] - x[i4][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
r2inv = 1.0/rsq;
|
||||
r6inv = r2inv*r2inv*r2inv;
|
||||
|
||||
if (implicit) forcecoul = qqrd2e * q[i1]*q[i4]*r2inv;
|
||||
else forcecoul = qqrd2e * q[i1]*q[i4]*sqrt(r2inv);
|
||||
forcelj = r6inv * (lj14_1[itype][jtype]*r6inv - lj14_2[itype][jtype]);
|
||||
fpair = weight[type] * (forcelj+forcecoul)*r2inv;
|
||||
|
||||
if (EFLAG) {
|
||||
ecoul = weight[type] * forcecoul;
|
||||
evdwl = r6inv * (lj14_3[itype][jtype]*r6inv - lj14_4[itype][jtype]);
|
||||
evdwl *= weight[type];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += delx*fpair;
|
||||
f[i1][1] += dely*fpair;
|
||||
f[i1][2] += delz*fpair;
|
||||
}
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] -= delx*fpair;
|
||||
f[i4][1] -= dely*fpair;
|
||||
f[i4][2] -= delz*fpair;
|
||||
}
|
||||
|
||||
if (EVFLAG) ev_tally_thr(force->pair,i1,i4,nlocal,NEWTON_BOND,
|
||||
evdwl,ecoul,fpair,delx,dely,delz,thr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(charmm/omp,DihedralCharmmOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_CHARMM_OMP_H
|
||||
#define LMP_DIHEDRAL_CHARMM_OMP_H
|
||||
|
||||
#include "dihedral_charmm.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralCharmmOMP : public DihedralCharmm, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralCharmmOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,531 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_class2_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.0000001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralClass2OMP::DihedralClass2OMP(class LAMMPS *lmp)
|
||||
: DihedralClass2(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralClass2OMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralClass2OMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,i,j,k,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral;
|
||||
double r1mag2,r1,r2mag2,r2,r3mag2,r3;
|
||||
double sb1,rb1,sb2,rb2,sb3,rb3,c0,r12c1;
|
||||
double r12c2,costh12,costh13,costh23,sc1,sc2,s1,s2,c;
|
||||
double cosphi,phi,sinphi,a11,a22,a33,a12,a13,a23,sx1,sx2;
|
||||
double sx12,sy1,sy2,sy12,sz1,sz2,sz12,dphi1,dphi2,dphi3;
|
||||
double de_dihedral,t1,t2,t3,t4,cos2phi,cos3phi,bt1,bt2;
|
||||
double bt3,sumbte,db,sumbtf,at1,at2,at3,da,da1,da2,r1_0;
|
||||
double r3_0,dr1,dr2,tk1,tk2,s12,sin2;
|
||||
double dcosphidr[4][3],dphidr[4][3],dbonddr[3][4][3],dthetadr[2][4][3];
|
||||
double fabcd[4][3];
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// distances
|
||||
|
||||
r1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
r1 = sqrt(r1mag2);
|
||||
r2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
r2 = sqrt(r2mag2);
|
||||
r3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
r3 = sqrt(r3mag2);
|
||||
|
||||
sb1 = 1.0/r1mag2;
|
||||
rb1 = 1.0/r1;
|
||||
sb2 = 1.0/r2mag2;
|
||||
rb2 = 1.0/r2;
|
||||
sb3 = 1.0/r3mag2;
|
||||
rb3 = 1.0/r3;
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// angles
|
||||
|
||||
r12c1 = rb1*rb2;
|
||||
r12c2 = rb2*rb3;
|
||||
costh12 = (vb1x*vb2x + vb1y*vb2y + vb1z*vb2z) * r12c1;
|
||||
costh13 = c0;
|
||||
costh23 = (vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z) * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - costh12*costh12,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - costh23*costh23,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + costh12*costh23) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
cosphi = c;
|
||||
phi = acos(c);
|
||||
|
||||
sinphi = sqrt(1.0 - c*c);
|
||||
sinphi = MAX(sinphi,SMALL);
|
||||
|
||||
a11 = -c*sb1*s1;
|
||||
a22 = sb2 * (2.0*costh13*s12 - c*(s1+s2));
|
||||
a33 = -c*sb3*s2;
|
||||
a12 = r12c1 * (costh12*c*s1 + costh23*s12);
|
||||
a13 = rb1*rb3*s12;
|
||||
a23 = r12c2 * (-costh23*c*s2 - costh12*s12);
|
||||
|
||||
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
// set up d(cos(phi))/d(r) and dphi/dr arrays
|
||||
|
||||
dcosphidr[0][0] = -sx1;
|
||||
dcosphidr[0][1] = -sy1;
|
||||
dcosphidr[0][2] = -sz1;
|
||||
dcosphidr[1][0] = sx2 + sx1;
|
||||
dcosphidr[1][1] = sy2 + sy1;
|
||||
dcosphidr[1][2] = sz2 + sz1;
|
||||
dcosphidr[2][0] = sx12 - sx2;
|
||||
dcosphidr[2][1] = sy12 - sy2;
|
||||
dcosphidr[2][2] = sz12 - sz2;
|
||||
dcosphidr[3][0] = -sx12;
|
||||
dcosphidr[3][1] = -sy12;
|
||||
dcosphidr[3][2] = -sz12;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
dphidr[i][j] = -dcosphidr[i][j] / sinphi;
|
||||
|
||||
// energy
|
||||
|
||||
dphi1 = phi - phi1[type];
|
||||
dphi2 = 2.0*phi - phi2[type];
|
||||
dphi3 = 3.0*phi - phi3[type];
|
||||
|
||||
if (EFLAG) edihedral = k1[type]*(1.0 - cos(dphi1)) +
|
||||
k2[type]*(1.0 - cos(dphi2)) +
|
||||
k3[type]*(1.0 - cos(dphi3));
|
||||
|
||||
de_dihedral = k1[type]*sin(dphi1) + 2.0*k2[type]*sin(dphi2) +
|
||||
3.0*k3[type]*sin(dphi3);
|
||||
|
||||
// torsion forces on all 4 atoms
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] = de_dihedral*dphidr[i][j];
|
||||
|
||||
// set up d(bond)/d(r) array
|
||||
// dbonddr(i,j,k) = bond i, atom j, coordinate k
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
dbonddr[i][j][k] = 0.0;
|
||||
|
||||
// bond1
|
||||
|
||||
dbonddr[0][0][0] = vb1x / r1;
|
||||
dbonddr[0][0][1] = vb1y / r1;
|
||||
dbonddr[0][0][2] = vb1z / r1;
|
||||
dbonddr[0][1][0] = -vb1x / r1;
|
||||
dbonddr[0][1][1] = -vb1y / r1;
|
||||
dbonddr[0][1][2] = -vb1z / r1;
|
||||
|
||||
// bond2
|
||||
|
||||
dbonddr[1][1][0] = vb2x / r2;
|
||||
dbonddr[1][1][1] = vb2y / r2;
|
||||
dbonddr[1][1][2] = vb2z / r2;
|
||||
dbonddr[1][2][0] = -vb2x / r2;
|
||||
dbonddr[1][2][1] = -vb2y / r2;
|
||||
dbonddr[1][2][2] = -vb2z / r2;
|
||||
|
||||
// bond3
|
||||
|
||||
dbonddr[2][2][0] = vb3x / r3;
|
||||
dbonddr[2][2][1] = vb3y / r3;
|
||||
dbonddr[2][2][2] = vb3z / r3;
|
||||
dbonddr[2][3][0] = -vb3x / r3;
|
||||
dbonddr[2][3][1] = -vb3y / r3;
|
||||
dbonddr[2][3][2] = -vb3z / r3;
|
||||
|
||||
// set up d(theta)/d(r) array
|
||||
// dthetadr(i,j,k) = angle i, atom j, coordinate k
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
dthetadr[i][j][k] = 0.0;
|
||||
|
||||
t1 = costh12 / r1mag2;
|
||||
t2 = costh23 / r2mag2;
|
||||
t3 = costh12 / r2mag2;
|
||||
t4 = costh23 / r3mag2;
|
||||
|
||||
// angle12
|
||||
|
||||
dthetadr[0][0][0] = sc1 * ((t1 * vb1x) - (vb2x * r12c1));
|
||||
dthetadr[0][0][1] = sc1 * ((t1 * vb1y) - (vb2y * r12c1));
|
||||
dthetadr[0][0][2] = sc1 * ((t1 * vb1z) - (vb2z * r12c1));
|
||||
|
||||
dthetadr[0][1][0] = sc1 * ((-t1 * vb1x) + (vb2x * r12c1) +
|
||||
(-t3 * vb2x) + (vb1x * r12c1));
|
||||
dthetadr[0][1][1] = sc1 * ((-t1 * vb1y) + (vb2y * r12c1) +
|
||||
(-t3 * vb2y) + (vb1y * r12c1));
|
||||
dthetadr[0][1][2] = sc1 * ((-t1 * vb1z) + (vb2z * r12c1) +
|
||||
(-t3 * vb2z) + (vb1z * r12c1));
|
||||
|
||||
dthetadr[0][2][0] = sc1 * ((t3 * vb2x) - (vb1x * r12c1));
|
||||
dthetadr[0][2][1] = sc1 * ((t3 * vb2y) - (vb1y * r12c1));
|
||||
dthetadr[0][2][2] = sc1 * ((t3 * vb2z) - (vb1z * r12c1));
|
||||
|
||||
// angle23
|
||||
|
||||
dthetadr[1][1][0] = sc2 * ((t2 * vb2x) + (vb3x * r12c2));
|
||||
dthetadr[1][1][1] = sc2 * ((t2 * vb2y) + (vb3y * r12c2));
|
||||
dthetadr[1][1][2] = sc2 * ((t2 * vb2z) + (vb3z * r12c2));
|
||||
|
||||
dthetadr[1][2][0] = sc2 * ((-t2 * vb2x) - (vb3x * r12c2) +
|
||||
(t4 * vb3x) + (vb2x * r12c2));
|
||||
dthetadr[1][2][1] = sc2 * ((-t2 * vb2y) - (vb3y * r12c2) +
|
||||
(t4 * vb3y) + (vb2y * r12c2));
|
||||
dthetadr[1][2][2] = sc2 * ((-t2 * vb2z) - (vb3z * r12c2) +
|
||||
(t4 * vb3z) + (vb2z * r12c2));
|
||||
|
||||
dthetadr[1][3][0] = -sc2 * ((t4 * vb3x) + (vb2x * r12c2));
|
||||
dthetadr[1][3][1] = -sc2 * ((t4 * vb3y) + (vb2y * r12c2));
|
||||
dthetadr[1][3][2] = -sc2 * ((t4 * vb3z) + (vb2z * r12c2));
|
||||
|
||||
// mid-bond/torsion coupling
|
||||
// energy on bond2 (middle bond)
|
||||
|
||||
cos2phi = cos(2.0*phi);
|
||||
cos3phi = cos(3.0*phi);
|
||||
|
||||
bt1 = mbt_f1[type] * cosphi;
|
||||
bt2 = mbt_f2[type] * cos2phi;
|
||||
bt3 = mbt_f3[type] * cos3phi;
|
||||
sumbte = bt1 + bt2 + bt3;
|
||||
db = r2 - mbt_r0[type];
|
||||
if (EFLAG) edihedral += db * sumbte;
|
||||
|
||||
// force on bond2
|
||||
|
||||
bt1 = -mbt_f1[type] * sinphi;
|
||||
bt2 = -2.0 * mbt_f2[type] * sin(2.0*phi);
|
||||
bt3 = -3.0 * mbt_f3[type] * sin(3.0*phi);
|
||||
sumbtf = bt1 + bt2 + bt3;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] += db*sumbtf*dphidr[i][j] + sumbte*dbonddr[1][i][j];
|
||||
|
||||
// end-bond/torsion coupling
|
||||
// energy on bond1 (first bond)
|
||||
|
||||
bt1 = ebt_f1_1[type] * cosphi;
|
||||
bt2 = ebt_f2_1[type] * cos2phi;
|
||||
bt3 = ebt_f3_1[type] * cos3phi;
|
||||
sumbte = bt1 + bt2 + bt3;
|
||||
|
||||
db = r1 - ebt_r0_1[type];
|
||||
if (EFLAG) edihedral += db * (bt1+bt2+bt3);
|
||||
|
||||
// force on bond1
|
||||
|
||||
bt1 = ebt_f1_1[type] * sinphi;
|
||||
bt2 = 2.0 * ebt_f2_1[type] * sin(2.0*phi);
|
||||
bt3 = 3.0 * ebt_f3_1[type] * sin(3.0*phi);
|
||||
sumbtf = bt1 + bt2 + bt3;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] -= db*sumbtf*dphidr[i][j] + sumbte*dbonddr[0][i][j];
|
||||
|
||||
// end-bond/torsion coupling
|
||||
// energy on bond3 (last bond)
|
||||
|
||||
bt1 = ebt_f1_2[type] * cosphi;
|
||||
bt2 = ebt_f2_2[type] * cos2phi;
|
||||
bt3 = ebt_f3_2[type] * cos3phi;
|
||||
sumbte = bt1 + bt2 + bt3;
|
||||
|
||||
db = r3 - ebt_r0_2[type];
|
||||
if (EFLAG) edihedral += db * (bt1+bt2+bt3);
|
||||
|
||||
// force on bond3
|
||||
|
||||
bt1 = -ebt_f1_2[type] * sinphi;
|
||||
bt2 = -2.0 * ebt_f2_2[type] * sin(2.0*phi);
|
||||
bt3 = -3.0 * ebt_f3_2[type] * sin(3.0*phi);
|
||||
sumbtf = bt1 + bt2 + bt3;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] += db*sumbtf*dphidr[i][j] + sumbte*dbonddr[2][i][j];
|
||||
|
||||
// angle/torsion coupling
|
||||
// energy on angle1
|
||||
|
||||
at1 = at_f1_1[type] * cosphi;
|
||||
at2 = at_f2_1[type] * cos2phi;
|
||||
at3 = at_f3_1[type] * cos3phi;
|
||||
sumbte = at1 + at2 + at3;
|
||||
|
||||
da = acos(costh12) - at_theta0_1[type];
|
||||
if (EFLAG) edihedral += da * (at1+at2+at3);
|
||||
|
||||
// force on angle1
|
||||
|
||||
bt1 = at_f1_1[type] * sinphi;
|
||||
bt2 = 2.0 * at_f2_1[type] * sin(2.0*phi);
|
||||
bt3 = 3.0 * at_f3_1[type] * sin(3.0*phi);
|
||||
sumbtf = bt1 + bt2 + bt3;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] -= da*sumbtf*dphidr[i][j] + sumbte*dthetadr[0][i][j];
|
||||
|
||||
// energy on angle2
|
||||
|
||||
at1 = at_f1_2[type] * cosphi;
|
||||
at2 = at_f2_2[type] * cos2phi;
|
||||
at3 = at_f3_2[type] * cos3phi;
|
||||
sumbte = at1 + at2 + at3;
|
||||
|
||||
da = acos(costh23) - at_theta0_2[type];
|
||||
if (EFLAG) edihedral += da * (at1+at2+at3);
|
||||
|
||||
// force on angle2
|
||||
|
||||
bt1 = -at_f1_2[type] * sinphi;
|
||||
bt2 = -2.0 * at_f2_2[type] * sin(2.0*phi);
|
||||
bt3 = -3.0 * at_f3_2[type] * sin(3.0*phi);
|
||||
sumbtf = bt1 + bt2 + bt3;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] += da*sumbtf*dphidr[i][j] + sumbte*dthetadr[1][i][j];
|
||||
|
||||
// angle/angle/torsion coupling
|
||||
|
||||
da1 = acos(costh12) - aat_theta0_1[type];
|
||||
da2 = acos(costh23) - aat_theta0_2[type];
|
||||
|
||||
if (EFLAG) edihedral += aat_k[type]*da1*da2*cosphi;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] -= aat_k[type] *
|
||||
(cosphi * (da2*dthetadr[0][i][j] - da1*dthetadr[1][i][j]) +
|
||||
sinphi * da1*da2*dphidr[i][j]);
|
||||
|
||||
// bond1/bond3 coupling
|
||||
|
||||
if (fabs(bb13t_k[type]) > SMALL) {
|
||||
|
||||
r1_0 = bb13t_r10[type];
|
||||
r3_0 = bb13t_r30[type];
|
||||
dr1 = r1 - r1_0;
|
||||
dr2 = r3 - r3_0;
|
||||
tk1 = -bb13t_k[type] * dr1 / r3;
|
||||
tk2 = -bb13t_k[type] * dr2 / r1;
|
||||
|
||||
if (EFLAG) edihedral += bb13t_k[type]*dr1*dr2;
|
||||
|
||||
fabcd[0][0] += tk2 * vb1x;
|
||||
fabcd[0][1] += tk2 * vb1y;
|
||||
fabcd[0][2] += tk2 * vb1z;
|
||||
|
||||
fabcd[1][0] -= tk2 * vb1x;
|
||||
fabcd[1][1] -= tk2 * vb1y;
|
||||
fabcd[1][2] -= tk2 * vb1z;
|
||||
|
||||
fabcd[2][0] -= tk1 * vb3x;
|
||||
fabcd[2][1] -= tk1 * vb3y;
|
||||
fabcd[2][2] -= tk1 * vb3z;
|
||||
|
||||
fabcd[3][0] += tk1 * vb3x;
|
||||
fabcd[3][1] += tk1 * vb3y;
|
||||
fabcd[3][2] += tk1 * vb3z;
|
||||
}
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += fabcd[0][0];
|
||||
f[i1][1] += fabcd[0][1];
|
||||
f[i1][2] += fabcd[0][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += fabcd[1][0];
|
||||
f[i2][1] += fabcd[1][1];
|
||||
f[i2][2] += fabcd[1][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += fabcd[2][0];
|
||||
f[i3][1] += fabcd[2][1];
|
||||
f[i3][2] += fabcd[2][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += fabcd[3][0];
|
||||
f[i4][1] += fabcd[3][1];
|
||||
f[i4][2] += fabcd[3][2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,
|
||||
fabcd[0],fabcd[2],fabcd[3],
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(class2/omp,DihedralClass2OMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_CLASS2_OMP_H
|
||||
#define LMP_DIHEDRAL_CLASS2_OMP_H
|
||||
|
||||
#include "dihedral_class2.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralClass2OMP : public DihedralClass2, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralClass2OMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,262 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_cosine_shift_exp_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralCosineShiftExpOMP::DihedralCosineShiftExpOMP(class LAMMPS *lmp)
|
||||
: DihedralCosineShiftExp(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralCosineShiftExpOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralCosineShiftExpOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
|
||||
double df,fg,hg,fga,hgb,gaa,gbb;
|
||||
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
|
||||
double c,s,sx2,sy2,sz2;
|
||||
double cccpsss,cssmscc,exp2;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c,s calculation
|
||||
|
||||
ax = vb1y*vb2zm - vb1z*vb2ym;
|
||||
ay = vb1z*vb2xm - vb1x*vb2zm;
|
||||
az = vb1x*vb2ym - vb1y*vb2xm;
|
||||
bx = vb3y*vb2zm - vb3z*vb2ym;
|
||||
by = vb3z*vb2xm - vb3x*vb2zm;
|
||||
bz = vb3x*vb2ym - vb3y*vb2xm;
|
||||
|
||||
rasq = ax*ax + ay*ay + az*az;
|
||||
rbsq = bx*bx + by*by + bz*bz;
|
||||
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
|
||||
rg = sqrt(rgsq);
|
||||
|
||||
rginv = ra2inv = rb2inv = 0.0;
|
||||
if (rg > 0) rginv = 1.0/rg;
|
||||
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||
rabinv = sqrt(ra2inv*rb2inv);
|
||||
|
||||
c = (ax*bx + ay*by + az*bz)*rabinv;
|
||||
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
double aa=a[type];
|
||||
double uumin=umin[type];
|
||||
|
||||
cccpsss = c*cost[type]+s*sint[type];
|
||||
cssmscc = c*sint[type]-s*cost[type];
|
||||
|
||||
if (doExpansion[type]) {
|
||||
// |a|<0.001 so use expansions relative precision <1e-5
|
||||
if (EFLAG) edihedral = -0.125*(1+cccpsss)*(4+aa*(cccpsss-1))*uumin;
|
||||
df=0.5*uumin*( cssmscc + 0.5*aa*cccpsss);
|
||||
} else {
|
||||
exp2=exp(0.5*aa*(1+cccpsss));
|
||||
if (EFLAG) edihedral = opt1[type]*(1-exp2);
|
||||
df= 0.5*opt1[type]*aa* ( exp2*cssmscc );
|
||||
}
|
||||
|
||||
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
|
||||
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
|
||||
fga = fg*ra2inv*rginv;
|
||||
hgb = hg*rb2inv*rginv;
|
||||
gaa = -ra2inv*rg;
|
||||
gbb = rb2inv*rg;
|
||||
|
||||
dtfx = gaa*ax;
|
||||
dtfy = gaa*ay;
|
||||
dtfz = gaa*az;
|
||||
dtgx = fga*ax - hgb*bx;
|
||||
dtgy = fga*ay - hgb*by;
|
||||
dtgz = fga*az - hgb*bz;
|
||||
dthx = gbb*bx;
|
||||
dthy = gbb*by;
|
||||
dthz = gbb*bz;
|
||||
|
||||
sx2 = df*dtgx;
|
||||
sy2 = df*dtgy;
|
||||
sz2 = df*dtgz;
|
||||
|
||||
f1[0] = df*dtfx;
|
||||
f1[1] = df*dtfy;
|
||||
f1[2] = df*dtfz;
|
||||
|
||||
f2[0] = sx2 - f1[0];
|
||||
f2[1] = sy2 - f1[1];
|
||||
f2[2] = sz2 - f1[2];
|
||||
|
||||
f4[0] = df*dthx;
|
||||
f4[1] = df*dthy;
|
||||
f4[2] = df*dthz;
|
||||
|
||||
f3[0] = -sx2 - f4[0];
|
||||
f3[1] = -sy2 - f4[1];
|
||||
f3[2] = -sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(cosine/shift/exp/omp,DihedralCosineShiftExpOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_COSINE_SHIFT_EXP_OMP_H
|
||||
#define LMP_DIHEDRAL_COSINE_SHIFT_EXP_OMP_H
|
||||
|
||||
#include "dihedral_cosine_shift_exp.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralCosineShiftExpOMP : public DihedralCosineShiftExp, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralCosineShiftExpOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,269 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_harmonic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralHarmonicOMP::DihedralHarmonicOMP(class LAMMPS *lmp)
|
||||
: DihedralHarmonic(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHarmonicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralHarmonicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,i,m,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
|
||||
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
|
||||
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
|
||||
double c,s,p,sx2,sy2,sz2;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c,s calculation
|
||||
|
||||
ax = vb1y*vb2zm - vb1z*vb2ym;
|
||||
ay = vb1z*vb2xm - vb1x*vb2zm;
|
||||
az = vb1x*vb2ym - vb1y*vb2xm;
|
||||
bx = vb3y*vb2zm - vb3z*vb2ym;
|
||||
by = vb3z*vb2xm - vb3x*vb2zm;
|
||||
bz = vb3x*vb2ym - vb3y*vb2xm;
|
||||
|
||||
rasq = ax*ax + ay*ay + az*az;
|
||||
rbsq = bx*bx + by*by + bz*bz;
|
||||
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
|
||||
rg = sqrt(rgsq);
|
||||
|
||||
rginv = ra2inv = rb2inv = 0.0;
|
||||
if (rg > 0) rginv = 1.0/rg;
|
||||
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||
rabinv = sqrt(ra2inv*rb2inv);
|
||||
|
||||
c = (ax*bx + ay*by + az*bz)*rabinv;
|
||||
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
m = multiplicity[type];
|
||||
p = 1.0;
|
||||
ddf1 = df1 = 0.0;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
ddf1 = p*c - df1*s;
|
||||
df1 = p*s + df1*c;
|
||||
p = ddf1;
|
||||
}
|
||||
|
||||
p = p*cos_shift[type] + df1*sin_shift[type];
|
||||
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
|
||||
df1 *= -m;
|
||||
p += 1.0;
|
||||
|
||||
if (m == 0) {
|
||||
p = 1.0 + cos_shift[type];
|
||||
df1 = 0.0;
|
||||
}
|
||||
|
||||
if (EFLAG) edihedral = k[type] * p;
|
||||
|
||||
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
|
||||
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
|
||||
fga = fg*ra2inv*rginv;
|
||||
hgb = hg*rb2inv*rginv;
|
||||
gaa = -ra2inv*rg;
|
||||
gbb = rb2inv*rg;
|
||||
|
||||
dtfx = gaa*ax;
|
||||
dtfy = gaa*ay;
|
||||
dtfz = gaa*az;
|
||||
dtgx = fga*ax - hgb*bx;
|
||||
dtgy = fga*ay - hgb*by;
|
||||
dtgz = fga*az - hgb*bz;
|
||||
dthx = gbb*bx;
|
||||
dthy = gbb*by;
|
||||
dthz = gbb*bz;
|
||||
|
||||
df = -k[type] * df1;
|
||||
|
||||
sx2 = df*dtgx;
|
||||
sy2 = df*dtgy;
|
||||
sz2 = df*dtgz;
|
||||
|
||||
f1[0] = df*dtfx;
|
||||
f1[1] = df*dtfy;
|
||||
f1[2] = df*dtfz;
|
||||
|
||||
f2[0] = sx2 - f1[0];
|
||||
f2[1] = sy2 - f1[1];
|
||||
f2[2] = sz2 - f1[2];
|
||||
|
||||
f4[0] = df*dthx;
|
||||
f4[1] = df*dthy;
|
||||
f4[2] = df*dthz;
|
||||
|
||||
f3[0] = -sx2 - f4[0];
|
||||
f3[1] = -sy2 - f4[1];
|
||||
f3[2] = -sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(harmonic/omp,DihedralHarmonicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_HARMONIC_OMP_H
|
||||
#define LMP_DIHEDRAL_HARMONIC_OMP_H
|
||||
|
||||
#include "dihedral_harmonic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralHarmonicOMP : public DihedralHarmonic, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralHarmonicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,282 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_helix_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "math_const.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
#define SMALLER 0.00001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralHelixOMP::DihedralHelixOMP(class LAMMPS *lmp)
|
||||
: DihedralHelix(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralHelixOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralHelixOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx2,sy2,sz2;
|
||||
double s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
cx = vb1y*vb2z - vb1z*vb2y;
|
||||
cy = vb1z*vb2x - vb1x*vb2z;
|
||||
cz = vb1x*vb2y - vb1y*vb2x;
|
||||
cmag = sqrt(cx*cx + cy*cy + cz*cz);
|
||||
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
phi = acos(c);
|
||||
if (dx < 0.0) phi *= -1.0;
|
||||
si = sin(phi);
|
||||
if (fabs(si) < SMALLER) si = SMALLER;
|
||||
siinv = 1.0/si;
|
||||
|
||||
pd = -aphi[type] + 3.0*bphi[type]*sin(3.0*phi)*siinv +
|
||||
cphi[type]*sin(phi + MY_PI4)*siinv;
|
||||
|
||||
if (EFLAG) edihedral = aphi[type]*(1.0 - c) + bphi[type]*(1.0 + cos(3.0*phi)) +
|
||||
cphi[type]*(1.0 + cos(phi + MY_PI4));
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = c*sb1*s1;
|
||||
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = c*sb3*s2;
|
||||
a12 = -r12c1 * (c1mag*c*s1 + c2mag*s12);
|
||||
a13 = -rb1*rb3*s12;
|
||||
a23 = r12c2 * (c2mag*c*s2 + c1mag*s12);
|
||||
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
|
||||
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
|
||||
f2[0] = -sx2 - f1[0];
|
||||
f2[1] = -sy2 - f1[1];
|
||||
f2[2] = -sz2 - f1[2];
|
||||
|
||||
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
f3[0] = sx2 - f4[0];
|
||||
f3[1] = sy2 - f4[1];
|
||||
f3[2] = sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(helix/omp,DihedralHelixOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_HELIX_OMP_H
|
||||
#define LMP_DIHEDRAL_HELIX_OMP_H
|
||||
|
||||
#include "dihedral_helix.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralHelixOMP : public DihedralHelix, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralHelixOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,269 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_multi_harmonic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralMultiHarmonicOMP::DihedralMultiHarmonicOMP(class LAMMPS *lmp)
|
||||
: DihedralMultiHarmonic(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralMultiHarmonicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralMultiHarmonicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx2,sy2,sz2;
|
||||
double s2,sin2;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = sum (i=1,5) a_i * c**(i-1)
|
||||
// pd = dp/dc
|
||||
|
||||
pd = a2[type] + c*(2.0*a3[type] + c*(3.0*a4[type] + c*4.0*a5[type]));
|
||||
|
||||
if (EFLAG)
|
||||
edihedral = a1[type] + c*(a2[type] + c*(a3[type] + c*(a4[type] + c*a5[type])));
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = c*sb1*s1;
|
||||
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = c*sb3*s2;
|
||||
a12 = -r12c1*(c1mag*c*s1 + c2mag*s12);
|
||||
a13 = -rb1*rb3*s12;
|
||||
a23 = r12c2*(c2mag*c*s2 + c1mag*s12);
|
||||
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
|
||||
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
|
||||
f2[0] = -sx2 - f1[0];
|
||||
f2[1] = -sy2 - f1[1];
|
||||
f2[2] = -sz2 - f1[2];
|
||||
|
||||
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
f3[0] = sx2 - f4[0];
|
||||
f3[1] = sy2 - f4[1];
|
||||
f3[2] = sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(multi/harmonic/omp,DihedralMultiHarmonicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_MULTI_HARMONIC_OMP_H
|
||||
#define LMP_DIHEDRAL_MULTI_HARMONIC_OMP_H
|
||||
|
||||
#include "dihedral_multi_harmonic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralMultiHarmonicOMP : public DihedralMultiHarmonic, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralMultiHarmonicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,285 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_opls_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
#define SMALLER 0.00001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralOPLSOMP::DihedralOPLSOMP(class LAMMPS *lmp)
|
||||
: DihedralOPLS(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralOPLSOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralOPLSOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s12,c,pd,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx2,sy2,sz2;
|
||||
double s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
|
||||
sc1 = sqrt(sin2);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
|
||||
sc2 = sqrt(sin2);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
cx = vb1y*vb2z - vb1z*vb2y;
|
||||
cy = vb1z*vb2x - vb1x*vb2z;
|
||||
cz = vb1x*vb2y - vb1y*vb2x;
|
||||
cmag = sqrt(cx*cx + cy*cy + cz*cz);
|
||||
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Dihedral problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = sum (i=1,4) k_i * (1 + (-1)**(i+1)*cos(i*phi) )
|
||||
// pd = dp/dc
|
||||
|
||||
phi = acos(c);
|
||||
if (dx < 0.0) phi *= -1.0;
|
||||
si = sin(phi);
|
||||
if (fabs(si) < SMALLER) si = SMALLER;
|
||||
siinv = 1.0/si;
|
||||
|
||||
pd = k1[type] - 2.0*k2[type]*sin(2.0*phi)*siinv +
|
||||
3.0*k3[type]*sin(3.0*phi)*siinv - 4.0*k4[type]*sin(4.0*phi)*siinv;
|
||||
|
||||
if (EFLAG) edihedral = k1[type]*(1.0 + c) + k2[type]*(1.0 - cos(2.0*phi))
|
||||
+ k3[type]*(1.0 + cos(3.0*phi)) + k4[type]*(1.0 - cos(4.0*phi));
|
||||
|
||||
|
||||
a = pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = c*sb1*s1;
|
||||
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = c*sb3*s2;
|
||||
a12 = -r12c1 * (c1mag*c*s1 + c2mag*s12);
|
||||
a13 = -rb1*rb3*s12;
|
||||
a23 = r12c2 * (c2mag*c*s2 + c1mag*s12);
|
||||
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
|
||||
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
|
||||
f2[0] = -sx2 - f1[0];
|
||||
f2[1] = -sy2 - f1[1];
|
||||
f2[2] = -sz2 - f1[2];
|
||||
|
||||
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
f3[0] = sx2 - f4[0];
|
||||
f3[1] = sy2 - f4[1];
|
||||
f3[2] = sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(opls/omp,DihedralOPLSOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_OPLS_OMP_H
|
||||
#define LMP_DIHEDRAL_OPLS_OMP_H
|
||||
|
||||
#include "dihedral_opls.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralOPLSOMP : public DihedralOPLS, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralOPLSOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,345 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "dihedral_table_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace DIHEDRAL_TABLE_NS;
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
DihedralTableOMP::DihedralTableOMP(class LAMMPS *lmp)
|
||||
: DihedralTable(lmp), ThrOMP(lmp,THR_DIHEDRAL)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void DihedralTableOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->ndihedrallist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void DihedralTableOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double edihedral,f1[3],f2[3],f3[3],f4[3];
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const dihedrallist = neighbor->dihedrallist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
// The dihedral angle "phi" is the angle between n123 and n234
|
||||
// the planes defined by atoms i1,i2,i3, and i2,i3,i4.
|
||||
//
|
||||
// Definitions of vectors: vb12, vb23, vb34, perp12on23
|
||||
// proj12on23, perp43on32, proj43on32
|
||||
//
|
||||
// Note: The positions of the 4 atoms are labeled x[i1], x[i2], x[i3], x[i4]
|
||||
// (which are also vectors)
|
||||
//
|
||||
// proj12on23 proj34on23
|
||||
// ---------> ----------->
|
||||
// .
|
||||
// .
|
||||
// .
|
||||
// x[i2] . x[i3]
|
||||
// . __@----------vb23-------->@ . . . . .
|
||||
// /|\ /| \ |
|
||||
// | / \ |
|
||||
// | / \ |
|
||||
// perp12vs23 / \ |
|
||||
// | / \ perp34vs23
|
||||
// | vb12 \ |
|
||||
// | / vb34 |
|
||||
// | / \ |
|
||||
// | / \ |
|
||||
// | / \ |
|
||||
// @ \ |
|
||||
// _\| \|/
|
||||
// x[i1] @
|
||||
//
|
||||
// x[i4]
|
||||
//
|
||||
|
||||
double vb12[g_dim]; // displacement vector from atom i1 towards atom i2
|
||||
// vb12[d] = x[i2][d] - x[i1][d] (for d=0,1,2)
|
||||
double vb23[g_dim]; // displacement vector from atom i2 towards atom i3
|
||||
// vb23[d] = x[i3][d] - x[i2][d] (for d=0,1,2)
|
||||
double vb34[g_dim]; // displacement vector from atom i3 towards atom i4
|
||||
// vb34[d] = x[i4][d] - x[i3][d] (for d=0,1,2)
|
||||
|
||||
// n123 & n234: These two unit vectors are normal to the planes
|
||||
// defined by atoms 1,2,3 and 2,3,4.
|
||||
double n123[g_dim]; //n123=vb23 x vb12 / |vb23 x vb12| ("x" is cross product)
|
||||
double n234[g_dim]; //n234=vb23 x vb34 / |vb23 x vb34| ("x" is cross product)
|
||||
|
||||
double proj12on23[g_dim];
|
||||
// proj12on23[d] = (vb23[d]/|vb23|) * DotProduct(vb12,vb23)/|vb12|*|vb23|
|
||||
double proj34on23[g_dim];
|
||||
// proj34on23[d] = (vb34[d]/|vb23|) * DotProduct(vb34,vb23)/|vb34|*|vb23|
|
||||
double perp12on23[g_dim];
|
||||
// perp12on23[d] = v12[d] - proj12on23[d]
|
||||
double perp34on23[g_dim];
|
||||
// perp34on23[d] = v34[d] - proj34on23[d]
|
||||
|
||||
edihedral = 0.0;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
|
||||
i1 = dihedrallist[n][0];
|
||||
i2 = dihedrallist[n][1];
|
||||
i3 = dihedrallist[n][2];
|
||||
i4 = dihedrallist[n][3];
|
||||
type = dihedrallist[n][4];
|
||||
|
||||
// ------ Step 1: Compute the dihedral angle "phi" ------
|
||||
//
|
||||
|
||||
// Phi() calculates the dihedral angle.
|
||||
// This function also calculates the vectors:
|
||||
// vb12, vb23, vb34, n123, and n234, which we will need later.
|
||||
|
||||
|
||||
double phi = Phi(x[i1], x[i2], x[i3], x[i4], domain,
|
||||
vb12, vb23, vb34, n123, n234);
|
||||
|
||||
|
||||
// ------ Step 2: Compute the gradient of phi with atomic position: ------
|
||||
//
|
||||
// Gradient variables:
|
||||
//
|
||||
// dphi_dx1, dphi_dx2, dphi_dx3, dphi_dx4 are the gradients of phi with
|
||||
// respect to the atomic positions of atoms i1, i2, i3, i4, respectively.
|
||||
// As an example, consider dphi_dx1. The d'th element is:
|
||||
double dphi_dx1[g_dim]; // d phi
|
||||
double dphi_dx2[g_dim]; // dphi_dx1[d] = ---------- (partial derivatives)
|
||||
double dphi_dx3[g_dim]; // d x[i1][d]
|
||||
double dphi_dx4[g_dim]; //where d=0,1,2 corresponds to x,y,z (if g_dim==3)
|
||||
|
||||
double dot123 = DotProduct(vb12, vb23);
|
||||
double dot234 = DotProduct(vb23, vb34);
|
||||
double L23sqr = DotProduct(vb23, vb23);
|
||||
double L23 = sqrt(L23sqr); // (central bond length)
|
||||
double inv_L23sqr = 0.0;
|
||||
double inv_L23 = 0.0;
|
||||
if (L23sqr != 0.0) {
|
||||
inv_L23sqr = 1.0 / L23sqr;
|
||||
inv_L23 = 1.0 / L23;
|
||||
}
|
||||
double neg_inv_L23 = -inv_L23;
|
||||
double dot123_over_L23sqr = dot123 * inv_L23sqr;
|
||||
double dot234_over_L23sqr = dot234 * inv_L23sqr;
|
||||
|
||||
for (int d=0; d < g_dim; ++d) {
|
||||
// See figure above for a visual definitions of these vectors:
|
||||
proj12on23[d] = vb23[d] * dot123_over_L23sqr;
|
||||
proj34on23[d] = vb23[d] * dot234_over_L23sqr;
|
||||
perp12on23[d] = vb12[d] - proj12on23[d];
|
||||
perp34on23[d] = vb34[d] - proj34on23[d];
|
||||
}
|
||||
|
||||
|
||||
// --- Compute the gradient vectors dphi/dx1 and dphi/dx4: ---
|
||||
|
||||
// These two gradients point in the direction of n123 and n234,
|
||||
// and are scaled by the distances of atoms 1 and 4 from the central axis.
|
||||
// Distance of atom 1 to central axis:
|
||||
double perp12on23_len = sqrt(DotProduct(perp12on23, perp12on23));
|
||||
// Distance of atom 4 to central axis:
|
||||
double perp34on23_len = sqrt(DotProduct(perp34on23, perp34on23));
|
||||
|
||||
double inv_perp12on23 = 0.0;
|
||||
if (perp12on23_len != 0.0) inv_perp12on23 = 1.0 / perp12on23_len;
|
||||
double inv_perp34on23 = 0.0;
|
||||
if (perp34on23_len != 0.0) inv_perp34on23 = 1.0 / perp34on23_len;
|
||||
|
||||
for (int d=0; d < g_dim; ++d) {
|
||||
dphi_dx1[d] = n123[d] * inv_perp12on23;
|
||||
dphi_dx4[d] = n234[d] * inv_perp34on23;
|
||||
}
|
||||
|
||||
// --- Compute the gradient vectors dphi/dx2 and dphi/dx3: ---
|
||||
//
|
||||
// This is more tricky because atoms 2 and 3 are shared by both planes
|
||||
// 123 and 234 (the angle between which defines "phi"). Moving either
|
||||
// one of these atoms effects both the 123 and 234 planes
|
||||
// Both the 123 and 234 planes intersect with the plane perpendicular to the
|
||||
// central bond axis (vb23). The two lines where these intersections occur
|
||||
// will shift when you move either atom 2 or atom 3. The angle between
|
||||
// these lines is the dihedral angle, phi. We can define four quantities:
|
||||
// dphi123_dx2 is the change in "phi" due to the movement of the 123 plane
|
||||
// ...as a result of moving atom 2.
|
||||
// dphi234_dx2 is the change in "phi" due to the movement of the 234 plane
|
||||
// ...as a result of moving atom 2.
|
||||
// dphi123_dx3 is the change in "phi" due to the movement of the 123 plane
|
||||
// ...as a result of moving atom 3.
|
||||
// dphi234_dx3 is the change in "phi" due to the movement of the 234 plane
|
||||
// ...as a result of moving atom 3.
|
||||
|
||||
double proj12on23_len = dot123 * inv_L23;
|
||||
double proj34on23_len = dot234 * inv_L23;
|
||||
// Interpretation:
|
||||
//The magnitude of "proj12on23_len" is the length of the proj12on23 vector.
|
||||
//The sign is positive if it points in the same direction as the central
|
||||
//bond (vb23). Otherwise it is negative. The same goes for "proj34on23".
|
||||
//(In the example figure in the comment above, both variables are positive.)
|
||||
|
||||
// The forumula used in the 8 lines below explained here:
|
||||
// "supporting_information/doc/gradient_formula_explanation/"
|
||||
double dphi123_dx2_coef = neg_inv_L23 * (L23 + proj12on23_len);
|
||||
double dphi234_dx2_coef = inv_L23 * proj34on23_len;
|
||||
|
||||
double dphi234_dx3_coef = neg_inv_L23 * (L23 + proj34on23_len);
|
||||
double dphi123_dx3_coef = inv_L23 * proj12on23_len;
|
||||
|
||||
for (int d=0; d < g_dim; ++d) {
|
||||
// Recall that the n123 and n234 plane normal vectors are proportional to
|
||||
// the dphi/dx1 and dphi/dx2 gradients vectors
|
||||
// It turns out we can save slightly more CPU cycles by expressing
|
||||
// dphi/dx2 and dphi/dx3 as linear combinations of dphi/dx1 and dphi/dx2
|
||||
// which we computed already (instead of n123 & n234).
|
||||
dphi_dx2[d] = dphi123_dx2_coef*dphi_dx1[d] + dphi234_dx2_coef*dphi_dx4[d];
|
||||
dphi_dx3[d] = dphi123_dx3_coef*dphi_dx1[d] + dphi234_dx3_coef*dphi_dx4[d];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DIH_DEBUG_NUM
|
||||
// ----- Numerical test? -----
|
||||
|
||||
cerr << " -- testing gradient for dihedral (n="<<n<<") for atoms ("
|
||||
<< i1 << "," << i2 << "," << i3 << "," << i4 << ") --" << endl;
|
||||
|
||||
PrintGradientComparison(*this, dphi_dx1, dphi_dx2, dphi_dx3, dphi_dx4,
|
||||
domain, x[i1], x[i2], x[i3], x[i4]);
|
||||
|
||||
for (int d=0; d < g_dim; ++d) {
|
||||
// The sum of all the gradients should be near 0. (translational symmetry)
|
||||
cerr <<"sum_gradients["<<d<<"]="<<dphi_dx1[d]<<"+"<<dphi_dx2[d]<<"+"<<dphi_dx3[d]<<"+"<<dphi_dx4[d]<<"="<<dphi_dx1[d]+dphi_dx2[d]+dphi_dx3[d]+dphi_dx4[d]<<endl;
|
||||
// These should sum to zero
|
||||
assert(abs(dphi_dx1[d]+dphi_dx2[d]+dphi_dx3[d]+dphi_dx4[d]) < 0.0002/L23);
|
||||
}
|
||||
#endif // #ifdef DIH_DEBUG_NUM
|
||||
|
||||
|
||||
|
||||
|
||||
// ----- Step 3: Calculate the energy and force in the phi direction -----
|
||||
|
||||
// tabulated force & energy
|
||||
double u, m_du_dphi; //u = energy. m_du_dphi = "minus" du/dphi
|
||||
assert((0.0 <= phi) && (phi <= TWOPI));
|
||||
|
||||
uf_lookup(type, phi, u, m_du_dphi);
|
||||
|
||||
|
||||
if (EFLAG) edihedral = u;
|
||||
|
||||
// ----- Step 4: Calculate the force direction in real space -----
|
||||
|
||||
// chain rule:
|
||||
// d U d U d phi
|
||||
// -f = ----- = ----- * -----
|
||||
// d x d phi d x
|
||||
for(int d=0; d < g_dim; ++d) {
|
||||
f1[d] = m_du_dphi * dphi_dx1[d];
|
||||
f2[d] = m_du_dphi * dphi_dx2[d];
|
||||
f3[d] = m_du_dphi * dphi_dx3[d];
|
||||
f4[d] = m_du_dphi * dphi_dx4[d];
|
||||
}
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,edihedral,f1,f3,f4,
|
||||
vb12[0],vb12[1],vb12[2],vb23[0],vb23[1],vb23[2],vb34[0],
|
||||
vb34[1],vb34[2],thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DIHEDRAL_CLASS
|
||||
|
||||
DihedralStyle(table/omp,DihedralTableOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_DIHEDRAL_TABLE_OMP_H
|
||||
#define LMP_DIHEDRAL_TABLE_OMP_H
|
||||
|
||||
#include "dihedral_table.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class DihedralTableOMP : public DihedralTable, public ThrOMP {
|
||||
|
||||
public:
|
||||
DihedralTableOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,415 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 authors: Roy Pollock (LLNL), Paul Crozier (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "ewald_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "math_const.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
#define SMALL 0.00001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
EwaldOMP::EwaldOMP(LAMMPS *lmp, int narg, char **arg)
|
||||
: Ewald(lmp, narg, arg), ThrOMP(lmp, THR_KSPACE)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void EwaldOMP::allocate()
|
||||
{
|
||||
Ewald::allocate();
|
||||
|
||||
// always re-allocate for simplicity.
|
||||
delete[] sfacrl;
|
||||
delete[] sfacim;
|
||||
|
||||
sfacrl = new double[kmax3d*comm->nthreads];
|
||||
sfacim = new double[kmax3d*comm->nthreads];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute the Ewald long-range force, energy, virial
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void EwaldOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
// set energy/virial flags
|
||||
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = evflag_atom = eflag_global = vflag_global =
|
||||
eflag_atom = vflag_atom = 0;
|
||||
|
||||
// extend size of per-atom arrays if necessary
|
||||
|
||||
if (atom->nlocal > nmax) {
|
||||
memory->destroy(ek);
|
||||
memory->destroy3d_offset(cs,-kmax_created);
|
||||
memory->destroy3d_offset(sn,-kmax_created);
|
||||
nmax = atom->nmax;
|
||||
memory->create(ek,nmax,3,"ewald:ek");
|
||||
memory->create3d_offset(cs,-kmax,kmax,3,nmax,"ewald:cs");
|
||||
memory->create3d_offset(sn,-kmax,kmax,3,nmax,"ewald:sn");
|
||||
kmax_created = kmax;
|
||||
}
|
||||
|
||||
// partial structure factors on each processor
|
||||
// total structure factor by summing over procs
|
||||
|
||||
eik_dot_r();
|
||||
MPI_Allreduce(sfacrl,sfacrl_all,kcount,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(sfacim,sfacim_all,kcount,MPI_DOUBLE,MPI_SUM,world);
|
||||
|
||||
// K-space portion of electric field
|
||||
// double loop over K-vectors and local atoms
|
||||
|
||||
double * const * const f = atom->f;
|
||||
const double * const q = atom->q;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int nlocal = atom->nlocal;
|
||||
const double qscale = force->qqrd2e * scale;
|
||||
|
||||
double eng_tmp = 0.0;
|
||||
double v0,v1,v2,v3,v4,v5;
|
||||
v0=v1=v2=v3=v4=v5=0.0;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag) reduction(+:eng_tmp,v0,v1,v2,v3,v4,v5)
|
||||
#endif
|
||||
{
|
||||
|
||||
int i,j,k,ifrom,ito,tid;
|
||||
int kx,ky,kz;
|
||||
double cypz,sypz,exprl,expim,partial;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, nlocal, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, 0, NULL, NULL, thr);
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
ek[i][0] = 0.0;
|
||||
ek[i][1] = 0.0;
|
||||
ek[i][2] = 0.0;
|
||||
}
|
||||
|
||||
for (k = 0; k < kcount; k++) {
|
||||
kx = kxvecs[k];
|
||||
ky = kyvecs[k];
|
||||
kz = kzvecs[k];
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cypz = cs[ky][1][i]*cs[kz][2][i] - sn[ky][1][i]*sn[kz][2][i];
|
||||
sypz = sn[ky][1][i]*cs[kz][2][i] + cs[ky][1][i]*sn[kz][2][i];
|
||||
exprl = cs[kx][0][i]*cypz - sn[kx][0][i]*sypz;
|
||||
expim = sn[kx][0][i]*cypz + cs[kx][0][i]*sypz;
|
||||
partial = expim*sfacrl_all[k] - exprl*sfacim_all[k];
|
||||
ek[i][0] += partial*eg[k][0];
|
||||
ek[i][1] += partial*eg[k][1];
|
||||
ek[i][2] += partial*eg[k][2];
|
||||
|
||||
if (evflag_atom) {
|
||||
const double partial_peratom = exprl*sfacrl_all[k] + expim*sfacim_all[k];
|
||||
if (eflag_atom) eatom[i] += q[i]*ug[k]*partial_peratom;
|
||||
if (vflag_atom)
|
||||
for (j = 0; j < 6; j++)
|
||||
vatom[i][j] += ug[k]*vg[k][j]*partial_peratom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert E-field to force
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
const double fac = qscale*q[i];
|
||||
f[i][0] += fac*ek[i][0];
|
||||
f[i][1] += fac*ek[i][1];
|
||||
f[i][2] += fac*ek[i][2];
|
||||
}
|
||||
|
||||
// global energy
|
||||
|
||||
if (eflag_global) {
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp for private(k)
|
||||
#endif
|
||||
for (k = 0; k < kcount; k++)
|
||||
eng_tmp += ug[k] * (sfacrl_all[k]*sfacrl_all[k] +
|
||||
sfacim_all[k]*sfacim_all[k]);
|
||||
}
|
||||
|
||||
// global virial
|
||||
|
||||
if (vflag_global) {
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp for private(k)
|
||||
#endif
|
||||
for (k = 0; k < kcount; k++) {
|
||||
double uk = ug[k] * (sfacrl_all[k]*sfacrl_all[k] + sfacim_all[k]*sfacim_all[k]);
|
||||
v0 += uk*vg[k][0];
|
||||
v1 += uk*vg[k][1];
|
||||
v2 += uk*vg[k][2];
|
||||
v3 += uk*vg[k][3];
|
||||
v4 += uk*vg[k][4];
|
||||
v5 += uk*vg[k][5];
|
||||
}
|
||||
}
|
||||
|
||||
// per-atom energy/virial
|
||||
// energy includes self-energy correction
|
||||
|
||||
if (evflag_atom) {
|
||||
if (eflag_atom) {
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
eatom[i] -= g_ewald*q[i]*q[i]/MY_PIS + MY_PI2*q[i]*qsum /
|
||||
(g_ewald*g_ewald*volume);
|
||||
eatom[i] *= qscale;
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag_atom)
|
||||
for (i = ifrom; i < ito; i++)
|
||||
for (j = 0; j < 6; j++) vatom[i][j] *= q[i]*qscale;
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag,vflag,thr);
|
||||
} // end of omp parallel region
|
||||
|
||||
if (eflag_global) {
|
||||
eng_tmp -= g_ewald*qsqsum/MY_PIS +
|
||||
MY_PI2*qsum*qsum / (g_ewald*g_ewald*volume);
|
||||
energy = eng_tmp * qscale;
|
||||
}
|
||||
|
||||
if (vflag_global) {
|
||||
virial[0] = v0 * qscale;
|
||||
virial[1] = v1 * qscale;
|
||||
virial[2] = v2 * qscale;
|
||||
virial[3] = v3 * qscale;
|
||||
virial[4] = v4 * qscale;
|
||||
virial[5] = v5 * qscale;
|
||||
}
|
||||
|
||||
if (slabflag) slabcorr();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void EwaldOMP::eik_dot_r()
|
||||
{
|
||||
const double * const * const x = atom->x;
|
||||
const double * const q = atom->q;
|
||||
const int nlocal = atom->nlocal;
|
||||
const int nthreads = comm->nthreads;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none)
|
||||
#endif
|
||||
{
|
||||
int i,ifrom,ito,k,l,m,n,ic,tid;
|
||||
double cstr1,sstr1,cstr2,sstr2,cstr3,sstr3,cstr4,sstr4;
|
||||
double sqk,clpm,slpm;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, nlocal, nthreads);
|
||||
|
||||
double * const sfacrl_thr = sfacrl + tid*kmax3d;
|
||||
double * const sfacim_thr = sfacim + tid*kmax3d;
|
||||
|
||||
n = 0;
|
||||
|
||||
// (k,0,0), (0,l,0), (0,0,m)
|
||||
|
||||
for (ic = 0; ic < 3; ic++) {
|
||||
sqk = unitk[ic]*unitk[ic];
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cs[0][ic][i] = 1.0;
|
||||
sn[0][ic][i] = 0.0;
|
||||
cs[1][ic][i] = cos(unitk[ic]*x[i][ic]);
|
||||
sn[1][ic][i] = sin(unitk[ic]*x[i][ic]);
|
||||
cs[-1][ic][i] = cs[1][ic][i];
|
||||
sn[-1][ic][i] = -sn[1][ic][i];
|
||||
cstr1 += q[i]*cs[1][ic][i];
|
||||
sstr1 += q[i]*sn[1][ic][i];
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
}
|
||||
}
|
||||
|
||||
for (m = 2; m <= kmax; m++) {
|
||||
for (ic = 0; ic < 3; ic++) {
|
||||
sqk = m*unitk[ic] * m*unitk[ic];
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cs[m][ic][i] = cs[m-1][ic][i]*cs[1][ic][i] -
|
||||
sn[m-1][ic][i]*sn[1][ic][i];
|
||||
sn[m][ic][i] = sn[m-1][ic][i]*cs[1][ic][i] +
|
||||
cs[m-1][ic][i]*sn[1][ic][i];
|
||||
cs[-m][ic][i] = cs[m][ic][i];
|
||||
sn[-m][ic][i] = -sn[m][ic][i];
|
||||
cstr1 += q[i]*cs[m][ic][i];
|
||||
sstr1 += q[i]*sn[m][ic][i];
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,0), 2 = (k,-l,0)
|
||||
|
||||
for (k = 1; k <= kxmax; k++) {
|
||||
for (l = 1; l <= kymax; l++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cstr1 += q[i]*(cs[k][0][i]*cs[l][1][i] - sn[k][0][i]*sn[l][1][i]);
|
||||
sstr1 += q[i]*(sn[k][0][i]*cs[l][1][i] + cs[k][0][i]*sn[l][1][i]);
|
||||
cstr2 += q[i]*(cs[k][0][i]*cs[l][1][i] + sn[k][0][i]*sn[l][1][i]);
|
||||
sstr2 += q[i]*(sn[k][0][i]*cs[l][1][i] - cs[k][0][i]*sn[l][1][i]);
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
sfacrl_thr[n] = cstr2;
|
||||
sfacim_thr[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (0,l,m), 2 = (0,l,-m)
|
||||
|
||||
for (l = 1; l <= kymax; l++) {
|
||||
for (m = 1; m <= kzmax; m++) {
|
||||
sqk = (l*unitk[1] * l*unitk[1]) + (m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cstr1 += q[i]*(cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i]);
|
||||
sstr1 += q[i]*(sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i]);
|
||||
cstr2 += q[i]*(cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i]);
|
||||
sstr2 += q[i]*(sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i]);
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
sfacrl_thr[n] = cstr2;
|
||||
sfacim_thr[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,0,m), 2 = (k,0,-m)
|
||||
|
||||
for (k = 1; k <= kxmax; k++) {
|
||||
for (m = 1; m <= kzmax; m++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
cstr1 += q[i]*(cs[k][0][i]*cs[m][2][i] - sn[k][0][i]*sn[m][2][i]);
|
||||
sstr1 += q[i]*(sn[k][0][i]*cs[m][2][i] + cs[k][0][i]*sn[m][2][i]);
|
||||
cstr2 += q[i]*(cs[k][0][i]*cs[m][2][i] + sn[k][0][i]*sn[m][2][i]);
|
||||
sstr2 += q[i]*(sn[k][0][i]*cs[m][2][i] - cs[k][0][i]*sn[m][2][i]);
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
sfacrl_thr[n] = cstr2;
|
||||
sfacim_thr[n++] = sstr2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = (k,l,m), 2 = (k,-l,m), 3 = (k,l,-m), 4 = (k,-l,-m)
|
||||
|
||||
for (k = 1; k <= kxmax; k++) {
|
||||
for (l = 1; l <= kymax; l++) {
|
||||
for (m = 1; m <= kzmax; m++) {
|
||||
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]) +
|
||||
(m*unitk[2] * m*unitk[2]);
|
||||
if (sqk <= gsqmx) {
|
||||
cstr1 = 0.0;
|
||||
sstr1 = 0.0;
|
||||
cstr2 = 0.0;
|
||||
sstr2 = 0.0;
|
||||
cstr3 = 0.0;
|
||||
sstr3 = 0.0;
|
||||
cstr4 = 0.0;
|
||||
sstr4 = 0.0;
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
|
||||
slpm = sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
|
||||
cstr1 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr1 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
|
||||
slpm = -sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
|
||||
cstr2 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr2 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
|
||||
slpm = sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
|
||||
cstr3 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr3 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
|
||||
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
|
||||
slpm = -sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
|
||||
cstr4 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
|
||||
sstr4 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
|
||||
}
|
||||
sfacrl_thr[n] = cstr1;
|
||||
sfacim_thr[n++] = sstr1;
|
||||
sfacrl_thr[n] = cstr2;
|
||||
sfacim_thr[n++] = sstr2;
|
||||
sfacrl_thr[n] = cstr3;
|
||||
sfacim_thr[n++] = sstr3;
|
||||
sfacrl_thr[n] = cstr4;
|
||||
sfacim_thr[n++] = sstr4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sync_threads();
|
||||
data_reduce_thr(sfacrl,kmax3d,nthreads,1,tid);
|
||||
data_reduce_thr(sfacim,kmax3d,nthreads,1,tid);
|
||||
|
||||
} // end of parallel region
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- 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(ewald/omp,EwaldOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_EWALD_OMP_H
|
||||
#define LMP_EWALD_OMP_H
|
||||
|
||||
#include "ewald.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class EwaldOMP : public Ewald, public ThrOMP {
|
||||
public:
|
||||
EwaldOMP(class LAMMPS *, int, char **);
|
||||
virtual ~EwaldOMP() { };
|
||||
virtual void allocate();
|
||||
virtual void compute(int, int);
|
||||
|
||||
protected:
|
||||
virtual void eik_dot_r();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "fix_gravity_omp.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "domain.h"
|
||||
#include "input.h"
|
||||
#include "modify.h"
|
||||
#include "respa.h"
|
||||
#include "variable.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
enum{CHUTE,SPHERICAL,GRADIENT,VECTOR};
|
||||
enum{CONSTANT,EQUAL};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixGravityOMP::FixGravityOMP(LAMMPS *lmp, int narg, char **arg) :
|
||||
FixGravity(lmp, narg, arg) { }
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGravityOMP::post_force(int vflag)
|
||||
{
|
||||
// update gravity due to variables
|
||||
|
||||
if (varflag != CONSTANT) {
|
||||
modify->clearstep_compute();
|
||||
if (mstyle == EQUAL) magnitude = input->variable->compute_equal(mvar);
|
||||
if (vstyle == EQUAL) magnitude = input->variable->compute_equal(vvar);
|
||||
if (pstyle == EQUAL) magnitude = input->variable->compute_equal(pvar);
|
||||
if (tstyle == EQUAL) magnitude = input->variable->compute_equal(tvar);
|
||||
if (xstyle == EQUAL) magnitude = input->variable->compute_equal(xvar);
|
||||
if (ystyle == EQUAL) magnitude = input->variable->compute_equal(yvar);
|
||||
if (zstyle == EQUAL) magnitude = input->variable->compute_equal(zvar);
|
||||
modify->addstep_compute(update->ntimestep + 1);
|
||||
|
||||
set_acceleration();
|
||||
}
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = atom->f;
|
||||
double * const rmass = atom->rmass;
|
||||
double * const mass = atom->mass;
|
||||
int * const mask = atom->mask;
|
||||
int * const type = atom->type;
|
||||
const int nlocal = atom->nlocal;
|
||||
const double xacc_thr = xacc;
|
||||
const double yacc_thr = yacc;
|
||||
const double zacc_thr = zacc;
|
||||
double massone;
|
||||
|
||||
int i;
|
||||
eflag = 0;
|
||||
double grav = 0.0;
|
||||
|
||||
if (rmass) {
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i,massone) default(none) reduction(-:grav)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit) {
|
||||
massone = rmass[i];
|
||||
f[i][0] += massone*xacc_thr;
|
||||
f[i][1] += massone*yacc_thr;
|
||||
f[i][2] += massone*zacc_thr;
|
||||
grav -= massone * (xacc_thr*x[i][0] + yacc_thr*x[i][1] + zacc_thr*x[i][2]);
|
||||
}
|
||||
} else {
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i,massone) default(none) reduction(-:grav)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit) {
|
||||
massone = mass[type[i]];
|
||||
f[i][0] += massone*xacc_thr;
|
||||
f[i][1] += massone*yacc_thr;
|
||||
f[i][2] += massone*zacc_thr;
|
||||
grav -= massone * (xacc_thr*x[i][0] + yacc_thr*x[i][1] + zacc_thr*x[i][2]);
|
||||
}
|
||||
}
|
||||
egrav = grav;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixGravityOMP::post_force_respa(int vflag, int ilevel, int iloop)
|
||||
{
|
||||
if (ilevel == nlevels_respa-1) post_force(vflag);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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(gravity/omp,FixGravityOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_GRAVITY_OMP_H
|
||||
#define LMP_FIX_GRAVITY_OMP_H
|
||||
|
||||
#include "fix_gravity.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixGravityOMP : public FixGravity {
|
||||
|
||||
public:
|
||||
FixGravityOMP(class LAMMPS *, int, char **);
|
||||
virtual void post_force(int);
|
||||
virtual void post_force_respa(int, int, int);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "stdio.h"
|
||||
#include "string.h"
|
||||
#include "fix_nve_sphere_omp.h"
|
||||
#include "atom.h"
|
||||
#include "atom_vec.h"
|
||||
#include "update.h"
|
||||
#include "respa.h"
|
||||
#include "force.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
#define INERTIA 0.4 // moment of inertia prefactor for sphere
|
||||
|
||||
enum{NONE,DIPOLE};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESphereOMP::initial_integrate(int vflag)
|
||||
{
|
||||
double * const * const x = atom->x;
|
||||
double * const * const v = atom->v;
|
||||
const double * const * const f = atom->f;
|
||||
double * const * const omega = atom->omega;
|
||||
const double * const * const torque = atom->torque;
|
||||
const double * const radius = atom->radius;
|
||||
const double * const rmass = atom->rmass;
|
||||
const int * const mask = atom->mask;
|
||||
const int nlocal = (igroup == atom->firstgroup) ? atom->nfirst : atom->nlocal;
|
||||
int i;
|
||||
|
||||
// set timestep here since dt may have changed or come via rRESPA
|
||||
const double dtfrotate = dtf / INERTIA;
|
||||
|
||||
// update v,x,omega for all particles
|
||||
// d_omega/dt = torque / inertia
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i) default(none)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
const double dtfm = dtf / rmass[i];
|
||||
v[i][0] += dtfm * f[i][0];
|
||||
v[i][1] += dtfm * f[i][1];
|
||||
v[i][2] += dtfm * f[i][2];
|
||||
x[i][0] += dtv * v[i][0];
|
||||
x[i][1] += dtv * v[i][1];
|
||||
x[i][2] += dtv * v[i][2];
|
||||
|
||||
const double dtirotate = dtfrotate / (radius[i]*radius[i]*rmass[i]);
|
||||
omega[i][0] += dtirotate * torque[i][0];
|
||||
omega[i][1] += dtirotate * torque[i][1];
|
||||
omega[i][2] += dtirotate * torque[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
// update mu for dipoles
|
||||
// d_mu/dt = omega cross mu
|
||||
// renormalize mu to dipole length
|
||||
|
||||
if (extra == DIPOLE) {
|
||||
double * const * const mu = atom->mu;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i) default(none)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
double g0,g1,g2,msq,scale;
|
||||
if (mask[i] & groupbit) {
|
||||
if (mu[i][3] > 0.0) {
|
||||
g0 = mu[i][0] + dtv * (omega[i][1]*mu[i][2]-omega[i][2]*mu[i][1]);
|
||||
g1 = mu[i][1] + dtv * (omega[i][2]*mu[i][0]-omega[i][0]*mu[i][2]);
|
||||
g2 = mu[i][2] + dtv * (omega[i][0]*mu[i][1]-omega[i][1]*mu[i][0]);
|
||||
msq = g0*g0 + g1*g1 + g2*g2;
|
||||
scale = mu[i][3]/sqrt(msq);
|
||||
mu[i][0] = g0*scale;
|
||||
mu[i][1] = g1*scale;
|
||||
mu[i][2] = g2*scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESphereOMP::final_integrate()
|
||||
{
|
||||
double * const * const v = atom->v;
|
||||
const double * const * const f = atom->f;
|
||||
double * const * const omega = atom->omega;
|
||||
const double * const * const torque = atom->torque;
|
||||
const double * const rmass = atom->rmass;
|
||||
const double * const radius = atom->radius;
|
||||
const int * const mask = atom->mask;
|
||||
const int nlocal = (igroup == atom->firstgroup) ? atom->nfirst : atom->nlocal;
|
||||
int i;
|
||||
|
||||
// set timestep here since dt may have changed or come via rRESPA
|
||||
|
||||
const double dtfrotate = dtf / INERTIA;
|
||||
|
||||
// update v,omega for all particles
|
||||
// d_omega/dt = torque / inertia
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i) default(none)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit) {
|
||||
const double dtfm = dtf / rmass[i];
|
||||
v[i][0] += dtfm * f[i][0];
|
||||
v[i][1] += dtfm * f[i][1];
|
||||
v[i][2] += dtfm * f[i][2];
|
||||
|
||||
const double dtirotate = dtfrotate / (radius[i]*radius[i]*rmass[i]);
|
||||
omega[i][0] += dtirotate * torque[i][0];
|
||||
omega[i][1] += dtirotate * torque[i][1];
|
||||
omega[i][2] += dtirotate * torque[i][2];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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(nve/sphere/omp,FixNVESphereOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_NVE_SPHERE_OMP_H
|
||||
#define LMP_FIX_NVE_SPHERE_OMP_H
|
||||
|
||||
#include "fix_nve_sphere.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixNVESphereOMP : public FixNVESphere {
|
||||
public:
|
||||
FixNVESphereOMP(class LAMMPS *lmp, int narg, char **arg) :
|
||||
FixNVESphere(lmp, narg, arg) {};
|
||||
|
||||
virtual void initial_integrate(int);
|
||||
virtual void final_integrate();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,330 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
OpenMP based threading support for LAMMPS
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_request.h"
|
||||
#include "update.h"
|
||||
#include "integrate.h"
|
||||
#include "min.h"
|
||||
|
||||
#include "fix_omp.h"
|
||||
#include "thr_data.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
#include "pair_hybrid.h"
|
||||
#include "bond_hybrid.h"
|
||||
#include "angle_hybrid.h"
|
||||
#include "dihedral_hybrid.h"
|
||||
#include "improper_hybrid.h"
|
||||
#include "kspace.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "suffix.h"
|
||||
|
||||
#if defined(LMP_USER_CUDA)
|
||||
#include "cuda_modify_flags.h"
|
||||
#endif
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
#if defined(LMP_USER_CUDA)
|
||||
using namespace FixConstCuda;
|
||||
#endif
|
||||
|
||||
static int get_tid()
|
||||
{
|
||||
int tid = 0;
|
||||
#if defined(_OPENMP)
|
||||
tid = omp_get_thread_num();
|
||||
#endif
|
||||
return tid;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixOMP::FixOMP(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg),
|
||||
thr(NULL), last_omp_style(NULL), last_pair_hybrid(NULL),
|
||||
_nthr(-1), _neighbor(true), _newton(false)
|
||||
{
|
||||
if ((narg < 4) || (narg > 6)) error->all(FLERR,"Illegal fix OMP command");
|
||||
if (strcmp(arg[1],"all") != 0) error->all(FLERR,"Illegal fix OMP command");
|
||||
|
||||
int nthreads = 1;
|
||||
if (narg > 3) {
|
||||
#if defined(_OPENMP)
|
||||
if (strcmp(arg[3],"*") == 0)
|
||||
#pragma omp parallel default(none) shared(nthreads)
|
||||
nthreads = omp_get_num_threads();
|
||||
else
|
||||
nthreads = atoi(arg[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (nthreads < 1)
|
||||
error->all(FLERR,"Illegal number of threads requested.");
|
||||
|
||||
if (nthreads != comm->nthreads) {
|
||||
#if defined(_OPENMP)
|
||||
omp_set_num_threads(nthreads);
|
||||
#endif
|
||||
comm->nthreads = nthreads;
|
||||
if (comm->me == 0) {
|
||||
if (screen)
|
||||
fprintf(screen," reset %d OpenMP thread(s) per MPI task\n", nthreads);
|
||||
if (logfile)
|
||||
fprintf(logfile," reset %d OpenMP thread(s) per MPI task\n", nthreads);
|
||||
}
|
||||
}
|
||||
|
||||
if (narg > 4) {
|
||||
if (strcmp(arg[4],"force/neigh") == 0)
|
||||
_neighbor = true;
|
||||
else if (strcmp(arg[4],"force") == 0)
|
||||
_neighbor = false;
|
||||
else
|
||||
error->all(FLERR,"Illegal fix omp mode requested.");
|
||||
|
||||
if (comm->me == 0) {
|
||||
const char * const mode = _neighbor ? "OpenMP capable" : "serial";
|
||||
|
||||
if (screen)
|
||||
fprintf(screen," using %s neighbor list subroutines\n", mode);
|
||||
if (logfile)
|
||||
fprintf(logfile," using %s neighbor list subroutines\n", mode);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* to be enabled when we can switch between half and full neighbor lists */
|
||||
if (narg > 5) {
|
||||
if (strcmp(arg[5],"neigh/half") == 0)
|
||||
_newton = true;
|
||||
else if (strcmp(arg[5],"neigh/full") == 0)
|
||||
_newton = false;
|
||||
else
|
||||
error->all(FLERR,"Illegal fix OMP command");
|
||||
|
||||
if (comm->me == 0) {
|
||||
const char * const mode = _newton ? "half" : "full";
|
||||
|
||||
if (screen)
|
||||
fprintf(screen," using /omp styles with %s neighbor list builds\n", mode);
|
||||
if (logfile)
|
||||
fprintf(logfile," using /omp styles with %s neighbor list builds\n", mode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// allocate list for per thread accumulator manager class instances
|
||||
// and then have each thread create an instance of this class to
|
||||
// encourage the OS to use storage that is "close" to each thread's CPU.
|
||||
thr = new ThrData *[nthreads];
|
||||
_nthr = nthreads;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none)
|
||||
#endif
|
||||
{
|
||||
const int tid = get_tid();
|
||||
thr[tid] = new ThrData(tid);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixOMP::~FixOMP()
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none)
|
||||
#endif
|
||||
{
|
||||
const int tid = get_tid();
|
||||
delete thr[tid];
|
||||
}
|
||||
delete[] thr;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixOMP::setmask()
|
||||
{
|
||||
// compatibility with USER-CUDA
|
||||
// our fix doesn't need any data transfer.
|
||||
#if defined(LMP_USER_CUDA)
|
||||
if (lmp->cuda) {
|
||||
int mask = 0;
|
||||
mask |= PRE_FORCE_CUDA;
|
||||
mask |= PRE_FORCE_RESPA;
|
||||
mask |= MIN_PRE_FORCE;
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mask = 0;
|
||||
mask |= PRE_FORCE;
|
||||
mask |= PRE_FORCE_RESPA;
|
||||
mask |= MIN_PRE_FORCE;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixOMP::init()
|
||||
{
|
||||
if (strstr(update->integrate_style,"respa") != NULL)
|
||||
error->all(FLERR,"Cannot use r-RESPA with /omp styles");
|
||||
|
||||
int check_hybrid;
|
||||
last_pair_hybrid = NULL;
|
||||
last_omp_style = NULL;
|
||||
const char *last_omp_name = NULL;
|
||||
const char *last_hybrid_name = NULL;
|
||||
const char *last_force_name = NULL;
|
||||
|
||||
// determine which is the last force style with OpenMP
|
||||
// support as this is the one that has to reduce the forces
|
||||
|
||||
#define CheckStyleForOMP(name) \
|
||||
check_hybrid = 0; \
|
||||
if (force->name) { \
|
||||
if ( (strcmp(force->name ## _style,"hybrid") == 0) || \
|
||||
(strcmp(force->name ## _style,"hybrid/overlay") == 0) ) \
|
||||
check_hybrid=1; \
|
||||
if (force->name->suffix_flag & Suffix::OMP) { \
|
||||
last_force_name = (const char *) #name; \
|
||||
last_omp_name = force->name ## _style; \
|
||||
last_omp_style = (void *) force->name; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CheckHybridForOMP(name,Class) \
|
||||
if (check_hybrid) { \
|
||||
Class ## Hybrid *style = (Class ## Hybrid *) force->name; \
|
||||
for (int i=0; i < style->nstyles; i++) { \
|
||||
if (style->styles[i]->suffix_flag & Suffix::OMP) { \
|
||||
last_force_name = (const char *) #name; \
|
||||
last_omp_name = style->keywords[i]; \
|
||||
last_omp_style = style->styles[i]; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
CheckStyleForOMP(pair);
|
||||
CheckHybridForOMP(pair,Pair);
|
||||
if (check_hybrid) {
|
||||
last_pair_hybrid = last_omp_style;
|
||||
last_hybrid_name = last_omp_name;
|
||||
}
|
||||
|
||||
CheckStyleForOMP(bond);
|
||||
CheckHybridForOMP(bond,Bond);
|
||||
|
||||
CheckStyleForOMP(angle);
|
||||
CheckHybridForOMP(angle,Angle);
|
||||
|
||||
CheckStyleForOMP(dihedral);
|
||||
CheckHybridForOMP(dihedral,Dihedral);
|
||||
|
||||
CheckStyleForOMP(improper);
|
||||
CheckHybridForOMP(improper,Improper);
|
||||
|
||||
CheckStyleForOMP(kspace);
|
||||
|
||||
#undef CheckStyleForOMP
|
||||
#undef CheckHybridForOMP
|
||||
set_neighbor_omp();
|
||||
|
||||
// diagnostic output
|
||||
if (comm->me == 0) {
|
||||
if (last_omp_style) {
|
||||
if (last_pair_hybrid) {
|
||||
if (screen)
|
||||
fprintf(screen,"Hybrid pair style last /omp style %s\n", last_hybrid_name);
|
||||
if (logfile)
|
||||
fprintf(logfile,"Hybrid pair style last /omp style %s\n", last_hybrid_name);
|
||||
}
|
||||
if (screen)
|
||||
fprintf(screen,"Last active /omp style is %s_style %s\n",
|
||||
last_force_name, last_omp_name);
|
||||
if (logfile)
|
||||
fprintf(logfile,"Last active /omp style is %s_style %s\n",
|
||||
last_force_name, last_omp_name);
|
||||
} else {
|
||||
if (screen)
|
||||
fprintf(screen,"No /omp style for force computation currently active\n");
|
||||
if (logfile)
|
||||
fprintf(screen,"No /omp style for force computation currently active\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixOMP::set_neighbor_omp()
|
||||
{
|
||||
// select or deselect multi-threaded neighbor
|
||||
// list build depending on setting in package omp.
|
||||
// NOTE: since we are at the top of the list of
|
||||
// fixes, we cannot adjust neighbor lists from
|
||||
// other fixes. those have to be re-implemented
|
||||
// as /omp fix styles. :-(
|
||||
|
||||
const int neigh_omp = _neighbor ? 1 : 0;
|
||||
const int nrequest = neighbor->nrequest;
|
||||
|
||||
for (int i = 0; i < nrequest; ++i)
|
||||
neighbor->requests[i]->omp = neigh_omp;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
// adjust size and clear out per thread accumulator arrays
|
||||
void FixOMP::pre_force(int)
|
||||
{
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
|
||||
double **f = atom->f;
|
||||
double **torque = atom->torque;
|
||||
double *erforce = atom->erforce;
|
||||
double *de = atom->de;
|
||||
double *drho = atom->drho;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(f,torque,erforce,de,drho)
|
||||
#endif
|
||||
{
|
||||
const int tid = get_tid();
|
||||
thr[tid]->check_tid(tid);
|
||||
thr[tid]->init_force(nall,f,torque,erforce,de,drho);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
double FixOMP::memory_usage()
|
||||
{
|
||||
double bytes = comm->nthreads * (sizeof(ThrData *) + sizeof(ThrData));
|
||||
bytes += comm->nthreads * thr[0]->memory_usage();
|
||||
|
||||
return bytes;
|
||||
}
|
|
@ -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 FIX_CLASS
|
||||
|
||||
FixStyle(OMP,FixOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_OMP_H
|
||||
#define LMP_FIX_OMP_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ThrData;
|
||||
|
||||
class FixOMP : public Fix {
|
||||
friend class ThrOMP;
|
||||
|
||||
public:
|
||||
FixOMP(class LAMMPS *, int, char **);
|
||||
virtual ~FixOMP();
|
||||
virtual int setmask();
|
||||
virtual void init();
|
||||
virtual void pre_force(int);
|
||||
|
||||
virtual void setup_pre_force(int vflag) { pre_force(vflag); };
|
||||
virtual void min_setup_pre_force(int vflag) { pre_force(vflag); };
|
||||
virtual void min_pre_force(int vflag) { pre_force(vflag); };
|
||||
virtual void setup_pre_force_respa(int vflag,int) { pre_force(vflag); };
|
||||
virtual void pre_force_respa(int vflag,int,int) { pre_force(vflag); };
|
||||
|
||||
virtual double memory_usage();
|
||||
|
||||
ThrData *get_thr(int tid) { return thr[tid]; };
|
||||
int get_nthr() const { return _nthr; }
|
||||
|
||||
protected:
|
||||
ThrData **thr;
|
||||
void *last_omp_style; // pointer to the style that needs
|
||||
// to do the general force reduction
|
||||
void *last_pair_hybrid; // pointer to the pair style that needs
|
||||
// to call virial_fdot_compute()
|
||||
|
||||
public:
|
||||
bool get_neighbor() const {return _neighbor;};
|
||||
bool get_newton() const {return _newton;};
|
||||
|
||||
private:
|
||||
int _nthr; // number of currently active ThrData object
|
||||
bool _neighbor; // en/disable threads for neighbor list construction
|
||||
bool _newton; // en/disable newton's 3rd law for local atoms.
|
||||
|
||||
void set_neighbor_omp();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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: Mike Parks (SNL)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "fix_peri_neigh_omp.h"
|
||||
#include "fix_omp.h"
|
||||
#include "modify.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_request.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixPeriNeighOMP::init()
|
||||
{
|
||||
if (!first) return;
|
||||
|
||||
// determine status of neighbor flag of the omp package command
|
||||
int ifix = modify->find_fix("package_omp");
|
||||
int use_omp = 0;
|
||||
if (ifix >=0) {
|
||||
FixOMP * fix = static_cast<FixOMP *>(lmp->modify->fix[ifix]);
|
||||
if (fix->get_neighbor()) use_omp = 1;
|
||||
}
|
||||
|
||||
// need a full neighbor list once
|
||||
|
||||
int irequest = neighbor->request((void *) this);
|
||||
neighbor->requests[irequest]->pair = 0;
|
||||
neighbor->requests[irequest]->fix = 1;
|
||||
neighbor->requests[irequest]->half = 0;
|
||||
neighbor->requests[irequest]->full = 1;
|
||||
neighbor->requests[irequest]->omp = use_omp;
|
||||
neighbor->requests[irequest]->occasional = 1;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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(PERI_NEIGH_OMP,FixPeriNeighOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_PERI_NEIGH_OMP_H
|
||||
#define LMP_FIX_PERI_NEIGH_OMP_H
|
||||
|
||||
#include "fix_peri_neigh.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixPeriNeighOMP : public FixPeriNeigh {
|
||||
|
||||
public:
|
||||
FixPeriNeighOMP(class LAMMPS *lmp, int narg, char **argv) :
|
||||
FixPeriNeigh(lmp,narg,argv) {};
|
||||
virtual void init();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,192 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "lmptype.h"
|
||||
#include "mpi.h"
|
||||
#include "math.h"
|
||||
#include "fix_qeq_comb_omp.h"
|
||||
#include "fix_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "group.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "error.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neigh_request.h"
|
||||
#include "respa.h"
|
||||
#include "update.h"
|
||||
#include "pair_comb_omp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixQEQCombOMP::FixQEQCombOMP(LAMMPS *lmp, int narg, char **arg)
|
||||
: FixQEQComb(lmp, narg, arg)
|
||||
{
|
||||
if (narg < 5) error->all(FLERR,"Illegal fix qeq/comb/omp command");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixQEQCombOMP::init()
|
||||
{
|
||||
if (!atom->q_flag)
|
||||
error->all(FLERR,"Fix qeq/comb/omp requires atom attribute q");
|
||||
|
||||
comb = (PairComb *) force->pair_match("comb/omp",1);
|
||||
if (comb == NULL)
|
||||
comb = (PairComb *) force->pair_match("comb",1);
|
||||
if (comb == NULL) error->all(FLERR,"Must use pair_style comb or comb/omp with fix qeq/comb");
|
||||
|
||||
if (strstr(update->integrate_style,"respa"))
|
||||
nlevels_respa = ((Respa *) update->integrate)->nlevels;
|
||||
|
||||
ngroup = group->count(igroup);
|
||||
if (ngroup == 0) error->all(FLERR,"Fix qeq/comb group has no atoms");
|
||||
|
||||
// determine status of neighbor flag of the omp package command
|
||||
int ifix = modify->find_fix("package_omp");
|
||||
int use_omp = 0;
|
||||
if (ifix >=0) {
|
||||
FixOMP * fix = static_cast<FixOMP *>(lmp->modify->fix[ifix]);
|
||||
if (fix->get_neighbor()) use_omp = 1;
|
||||
}
|
||||
|
||||
int irequest = neighbor->request(this);
|
||||
neighbor->requests[irequest]->pair = 0;
|
||||
neighbor->requests[irequest]->fix = 1;
|
||||
neighbor->requests[irequest]->half = 0;
|
||||
neighbor->requests[irequest]->full = 1;
|
||||
neighbor->requests[irequest]->omp = use_omp;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixQEQCombOMP::post_force(int vflag)
|
||||
{
|
||||
int i,ii,iloop,loopmax,inum,*ilist;
|
||||
double heatpq,qmass,dtq,dtq2;
|
||||
double enegchkall,enegmaxall;
|
||||
|
||||
if (update->ntimestep % nevery) return;
|
||||
|
||||
// reallocate work arrays if necessary
|
||||
// qf = charge force
|
||||
// q1 = charge displacement
|
||||
// q2 = tmp storage of charge force for next iteration
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
memory->destroy(qf);
|
||||
memory->destroy(q1);
|
||||
memory->destroy(q2);
|
||||
nmax = atom->nmax;
|
||||
memory->create(qf,nmax,"qeq:qf");
|
||||
memory->create(q1,nmax,"qeq:q1");
|
||||
memory->create(q2,nmax,"qeq:q2");
|
||||
vector_atom = qf;
|
||||
}
|
||||
|
||||
// more loops for first-time charge equilibrium
|
||||
|
||||
iloop = 0;
|
||||
if (firstflag) loopmax = 500;
|
||||
else loopmax = 200;
|
||||
|
||||
// charge-equilibration loop
|
||||
|
||||
if (me == 0 && fp)
|
||||
fprintf(fp,"Charge equilibration on step " BIGINT_FORMAT "\n",
|
||||
update->ntimestep);
|
||||
|
||||
heatpq = 0.05;
|
||||
qmass = 0.016;
|
||||
dtq = 0.01;
|
||||
dtq2 = 0.5*dtq*dtq/qmass;
|
||||
|
||||
double enegchk = 0.0;
|
||||
double enegtot = 0.0;
|
||||
double enegmax = 0.0;
|
||||
|
||||
double *q = atom->q;
|
||||
int *mask = atom->mask;
|
||||
|
||||
inum = comb->list->inum;
|
||||
ilist = comb->list->ilist;
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
q1[i] = q2[i] = qf[i] = 0.0;
|
||||
}
|
||||
|
||||
for (iloop = 0; iloop < loopmax; iloop ++ ) {
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
if (mask[i] & groupbit) {
|
||||
q1[i] += qf[i]*dtq2 - heatpq*q1[i];
|
||||
q[i] += q1[i];
|
||||
}
|
||||
}
|
||||
comm->forward_comm_fix(this);
|
||||
|
||||
if(comb) enegtot = comb->yasu_char(qf,igroup);
|
||||
enegtot /= ngroup;
|
||||
enegchk = enegmax = 0.0;
|
||||
|
||||
for (ii = 0; ii < inum ; ii++) {
|
||||
i = ilist[ii];
|
||||
if (mask[i] & groupbit) {
|
||||
q2[i] = enegtot-qf[i];
|
||||
enegmax = MAX(enegmax,fabs(q2[i]));
|
||||
enegchk += fabs(q2[i]);
|
||||
qf[i] = q2[i];
|
||||
}
|
||||
}
|
||||
|
||||
MPI_Allreduce(&enegchk,&enegchkall,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
enegchk = enegchkall/ngroup;
|
||||
MPI_Allreduce(&enegmax,&enegmaxall,1,MPI_DOUBLE,MPI_MAX,world);
|
||||
enegmax = enegmaxall;
|
||||
|
||||
if (enegchk <= precision && enegmax <= 100.0*precision) break;
|
||||
|
||||
if (me == 0 && fp)
|
||||
fprintf(fp," iteration: %d, enegtot %.6g, "
|
||||
"enegmax %.6g, fq deviation: %.6g\n",
|
||||
iloop,enegtot,enegmax,enegchk);
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
if (mask[i] & groupbit)
|
||||
q1[i] += qf[i]*dtq2 - heatpq*q1[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (me == 0 && fp) {
|
||||
if (iloop == loopmax)
|
||||
fprintf(fp,"Charges did not converge in %d iterations\n",iloop);
|
||||
else
|
||||
fprintf(fp,"Charges converged in %d iterations to %.10f tolerance\n",
|
||||
iloop,enegchk);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(qeq/comb/omp,FixQEQCombOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_QEQ_COMB_OMP_H
|
||||
#define LMP_FIX_QEQ_COMB_OMP_H
|
||||
|
||||
#include "fix_qeq_comb.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixQEQCombOMP : public FixQEQComb {
|
||||
public:
|
||||
FixQEQCombOMP(class LAMMPS *, int, char **);
|
||||
virtual void init();
|
||||
virtual void post_force(int);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "stdio.h"
|
||||
#include "fix_shear_history_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "error.h"
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
#define MAXTOUCH 15
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
copy shear partner info from neighbor lists to atom arrays
|
||||
so can be exchanged with atoms
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void FixShearHistoryOMP::pre_exchange()
|
||||
{
|
||||
|
||||
const int nlocal = atom->nlocal;
|
||||
const int nghost = atom->nghost;
|
||||
const int nall = nlocal + nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
|
||||
int flag = 0;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(flag)
|
||||
#endif
|
||||
{
|
||||
|
||||
#if defined(_OPENMP)
|
||||
const int tid = omp_get_thread_num();
|
||||
#else
|
||||
const int tid = 0;
|
||||
#endif
|
||||
|
||||
// each thread works on a fixed chunk of local and ghost atoms.
|
||||
const int ldelta = 1 + nlocal/nthreads;
|
||||
const int lfrom = tid*ldelta;
|
||||
const int lmax = lfrom +ldelta;
|
||||
const int lto = (lmax > nlocal) ? nlocal : lmax;
|
||||
|
||||
const int gdelta = 1 + nghost/nthreads;
|
||||
const int gfrom = nlocal + tid*gdelta;
|
||||
const int gmax = gfrom + gdelta;
|
||||
const int gto = (gmax > nall) ? nall : gmax;
|
||||
|
||||
|
||||
int i,j,ii,jj,m,inum,jnum;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
int *touch,**firsttouch;
|
||||
double *shear,*allshear,**firstshear;
|
||||
|
||||
// zero npartners for all current atoms
|
||||
|
||||
for (i = lfrom; i < lto; i++) npartner[i] = 0;
|
||||
|
||||
// copy shear info from neighbor list atoms to atom arrays
|
||||
|
||||
int *tag = atom->tag;
|
||||
|
||||
NeighList *list = pair->list;
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
firsttouch = list->listgranhistory->firstneigh;
|
||||
firstshear = list->listgranhistory->firstdouble;
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
jlist = firstneigh[i];
|
||||
allshear = firstshear[i];
|
||||
jnum = numneigh[i];
|
||||
touch = firsttouch[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
if (touch[jj]) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
shear = &allshear[3*jj];
|
||||
|
||||
if ((i >= lfrom) && (i < lto)) {
|
||||
if (npartner[i] < MAXTOUCH) {
|
||||
m = npartner[i];
|
||||
partner[i][m] = tag[j];
|
||||
shearpartner[i][m][0] = shear[0];
|
||||
shearpartner[i][m][1] = shear[1];
|
||||
shearpartner[i][m][2] = shear[2];
|
||||
}
|
||||
npartner[i]++;
|
||||
}
|
||||
|
||||
if ((j >= lfrom) && (j < lto)) {
|
||||
if (npartner[j] < MAXTOUCH) {
|
||||
m = npartner[j];
|
||||
partner[j][m] = tag[i];
|
||||
shearpartner[j][m][0] = -shear[0];
|
||||
shearpartner[j][m][1] = -shear[1];
|
||||
shearpartner[j][m][2] = -shear[2];
|
||||
}
|
||||
npartner[j]++;
|
||||
}
|
||||
|
||||
if ((j >= gfrom) && (j < gto)) {
|
||||
npartner[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test for too many touching neighbors
|
||||
int myflag = 0;
|
||||
for (i = lfrom; i < lto; i++)
|
||||
if (npartner[i] >= MAXTOUCH) myflag = 1;
|
||||
|
||||
if (myflag)
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp atomic
|
||||
#endif
|
||||
++flag;
|
||||
}
|
||||
|
||||
int flag_all;
|
||||
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
|
||||
if (flag_all)
|
||||
error->all(FLERR,"Too many touching neighbors - boost MAXTOUCH");
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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(SHEAR_HISTORY/omp,FixShearHistoryOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_SHEAR_HISTORY_OMP_H
|
||||
#define LMP_FIX_SHEAR_HISTORY_OMP_H
|
||||
|
||||
#include "fix_shear_history.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixShearHistoryOMP : public FixShearHistory {
|
||||
|
||||
public:
|
||||
FixShearHistoryOMP(class LAMMPS *lmp, int narg, char **argv)
|
||||
: FixShearHistory(lmp,narg,argv) {};
|
||||
virtual void pre_exchange();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "fix_wall_gran_omp.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
|
||||
enum{XPLANE=0,YPLANE=1,ZPLANE=2,ZCYLINDER}; // XYZ PLANE need to be 0,1,2
|
||||
enum{HOOKE,HOOKE_HISTORY,HERTZ_HISTORY};
|
||||
|
||||
#define BIG 1.0e20
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixWallGranOMP::FixWallGranOMP(LAMMPS *lmp, int narg, char **arg) :
|
||||
FixWallGran(lmp, narg, arg) { }
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixWallGranOMP::post_force(int vflag)
|
||||
{
|
||||
double vwall[3];
|
||||
|
||||
// set position of wall to initial settings and velocity to 0.0
|
||||
// if wiggle or shear, set wall position and velocity accordingly
|
||||
|
||||
double wlo = lo;
|
||||
double whi = hi;
|
||||
vwall[0] = vwall[1] = vwall[2] = 0.0;
|
||||
if (wiggle) {
|
||||
double arg = omega * (update->ntimestep - time_origin) * dt;
|
||||
if (wallstyle == axis) {
|
||||
wlo = lo + amplitude - amplitude*cos(arg);
|
||||
whi = hi + amplitude - amplitude*cos(arg);
|
||||
}
|
||||
vwall[axis] = amplitude*omega*sin(arg);
|
||||
} else if (wshear) vwall[axis] = vshear;
|
||||
|
||||
// loop over all my atoms
|
||||
// rsq = distance from wall
|
||||
// dx,dy,dz = signed distance from wall
|
||||
// for rotating cylinder, reset vwall based on particle position
|
||||
// skip atom if not close enough to wall
|
||||
// if wall was set to NULL, it's skipped since lo/hi are infinity
|
||||
// compute force and torque on atom if close enough to wall
|
||||
// via wall potential matched to pair potential
|
||||
// set shear if pair potential stores history
|
||||
|
||||
double * const * const x = atom->x;
|
||||
double * const * const v = atom->v;
|
||||
double * const * const f = atom->f;
|
||||
double * const * const omega = atom->omega;
|
||||
double * const * const torque = atom->torque;
|
||||
double * const radius = atom->radius;
|
||||
double * const rmass = atom->rmass;
|
||||
const int * const mask = atom->mask;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
shearupdate = (update->setupflag) ? 0 : 1;
|
||||
|
||||
int i;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel for private(i) default(none) firstprivate(vwall,wlo,whi)
|
||||
#endif
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
|
||||
if (mask[i] & groupbit) {
|
||||
double dx,dy,dz,del1,del2,delxy,delr,rsq;
|
||||
|
||||
dx = dy = dz = 0.0;
|
||||
|
||||
if (wallstyle == XPLANE) {
|
||||
del1 = x[i][0] - wlo;
|
||||
del2 = whi - x[i][0];
|
||||
if (del1 < del2) dx = del1;
|
||||
else dx = -del2;
|
||||
} else if (wallstyle == YPLANE) {
|
||||
del1 = x[i][1] - wlo;
|
||||
del2 = whi - x[i][1];
|
||||
if (del1 < del2) dy = del1;
|
||||
else dy = -del2;
|
||||
} else if (wallstyle == ZPLANE) {
|
||||
del1 = x[i][2] - wlo;
|
||||
del2 = whi - x[i][2];
|
||||
if (del1 < del2) dz = del1;
|
||||
else dz = -del2;
|
||||
} else if (wallstyle == ZCYLINDER) {
|
||||
delxy = sqrt(x[i][0]*x[i][0] + x[i][1]*x[i][1]);
|
||||
delr = cylradius - delxy;
|
||||
if (delr > radius[i]) dz = cylradius;
|
||||
else {
|
||||
dx = -delr/delxy * x[i][0];
|
||||
dy = -delr/delxy * x[i][1];
|
||||
if (wshear && axis != 2) {
|
||||
vwall[0] = vshear * x[i][1]/delxy;
|
||||
vwall[1] = -vshear * x[i][0]/delxy;
|
||||
vwall[2] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rsq = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
if (rsq > radius[i]*radius[i]) {
|
||||
if (pairstyle != HOOKE) {
|
||||
shear[i][0] = 0.0;
|
||||
shear[i][1] = 0.0;
|
||||
shear[i][2] = 0.0;
|
||||
}
|
||||
} else {
|
||||
if (pairstyle == HOOKE)
|
||||
hooke(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
|
||||
radius[i],rmass[i]);
|
||||
else if (pairstyle == HOOKE_HISTORY)
|
||||
hooke_history(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
|
||||
radius[i],rmass[i],shear[i]);
|
||||
else if (pairstyle == HERTZ_HISTORY)
|
||||
hertz_history(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
|
||||
radius[i],rmass[i],shear[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixWallGranOMP::post_force_respa(int vflag, int ilevel, int iloop)
|
||||
{
|
||||
if (ilevel == nlevels_respa-1) post_force(vflag);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- 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(wall/gran/omp,FixWallGranOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_WALL_GRAN_OMP_H
|
||||
#define LMP_FIX_WALL_GRAN_OMP_H
|
||||
|
||||
#include "fix_wall_gran.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixWallGranOMP : public FixWallGran {
|
||||
|
||||
public:
|
||||
FixWallGranOMP(class LAMMPS *, int, char **);
|
||||
virtual void post_force(int);
|
||||
virtual void post_force_respa(int, int, int);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
|
||||
for f in *.h *.cpp
|
||||
do \
|
||||
sed -e '/#pragma omp/s/^\(.*default\)(none)\(.*\)$/\1(shared)\2/' \
|
||||
-e '/#pragma omp/s/shared([a-z0-9,_]\+)//' \
|
||||
-i.bak $f
|
||||
done
|
|
@ -0,0 +1,698 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_class2_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperClass2OMP::ImproperClass2OMP(class LAMMPS *lmp)
|
||||
: ImproperClass2(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperClass2OMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperClass2OMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,i,j,k,n,type;
|
||||
double eimproper;
|
||||
double delr[3][3],rmag[3],rinvmag[3],rmag2[3];
|
||||
double theta[3],costheta[3],sintheta[3];
|
||||
double cossqtheta[3],sinsqtheta[3],invstheta[3];
|
||||
double rABxrCB[3],rDBxrAB[3],rCBxrDB[3];
|
||||
double ddelr[3][4],dr[3][4][3],dinvr[3][4][3];
|
||||
double dthetadr[3][4][3],dinvsth[3][4][3];
|
||||
double dinv3r[4][3],dinvs3r[3][4][3];
|
||||
double drCBxrDB[3],rCBxdrDB[3],drDBxrAB[3],rDBxdrAB[3];
|
||||
double drABxrCB[3],rABxdrCB[3];
|
||||
double dot1,dot2,dd[3];
|
||||
double fdot[3][4][3],ftmp,invs3r[3],inv3r;
|
||||
double t,tt1,tt3,sc1;
|
||||
double dotCBDBAB,dotDBABCB,dotABCBDB;
|
||||
double chi,deltachi,d2chi,cossin2;
|
||||
double drAB[3][4][3],drCB[3][4][3],drDB[3][4][3];
|
||||
double dchi[3][4][3],dtotalchi[4][3];
|
||||
double schiABCD,chiABCD,schiCBDA,chiCBDA,schiDBAC,chiDBAC;
|
||||
double fabcd[4][3];
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++) {
|
||||
dthetadr[i][j][k] = 0.0;
|
||||
drAB[i][j][k] = 0.0;
|
||||
drCB[i][j][k] = 0.0;
|
||||
drDB[i][j][k] = 0.0;
|
||||
}
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
if (k0[type] == 0.0) continue;
|
||||
|
||||
// difference vectors
|
||||
|
||||
delr[0][0] = x[i1][0] - x[i2][0];
|
||||
delr[0][1] = x[i1][1] - x[i2][1];
|
||||
delr[0][2] = x[i1][2] - x[i2][2];
|
||||
|
||||
delr[1][0] = x[i3][0] - x[i2][0];
|
||||
delr[1][1] = x[i3][1] - x[i2][1];
|
||||
delr[1][2] = x[i3][2] - x[i2][2];
|
||||
|
||||
delr[2][0] = x[i4][0] - x[i2][0];
|
||||
delr[2][1] = x[i4][1] - x[i2][1];
|
||||
delr[2][2] = x[i4][2] - x[i2][2];
|
||||
|
||||
// bond lengths and associated values
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rmag2[i] = delr[i][0]*delr[i][0] + delr[i][1]*delr[i][1] +
|
||||
delr[i][2]*delr[i][2];
|
||||
rmag[i] = sqrt(rmag2[i]);
|
||||
rinvmag[i] = 1.0/rmag[i];
|
||||
}
|
||||
|
||||
// angle ABC, CBD, ABD
|
||||
|
||||
costheta[0] = (delr[0][0]*delr[1][0] + delr[0][1]*delr[1][1] +
|
||||
delr[0][2]*delr[1][2]) / (rmag[0]*rmag[1]);
|
||||
costheta[1] = (delr[1][0]*delr[2][0] + delr[1][1]*delr[2][1] +
|
||||
delr[1][2]*delr[2][2]) / (rmag[1]*rmag[2]);
|
||||
costheta[2] = (delr[0][0]*delr[2][0] + delr[0][1]*delr[2][1] +
|
||||
delr[0][2]*delr[2][2]) / (rmag[0]*rmag[2]);
|
||||
|
||||
// angle error check
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (costheta[i] == -1.0) {
|
||||
int me = comm->me;
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,
|
||||
"Improper problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me, thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (costheta[i] > 1.0) costheta[i] = 1.0;
|
||||
if (costheta[i] < -1.0) costheta[i] = -1.0;
|
||||
theta[i] = acos(costheta[i]);
|
||||
cossqtheta[i] = costheta[i]*costheta[i];
|
||||
sintheta[i] = sin(theta[i]);
|
||||
invstheta[i] = 1.0/sintheta[i];
|
||||
sinsqtheta[i] = sintheta[i]*sintheta[i];
|
||||
}
|
||||
|
||||
// cross & dot products
|
||||
|
||||
cross(delr[0],delr[1],rABxrCB);
|
||||
cross(delr[2],delr[0],rDBxrAB);
|
||||
cross(delr[1],delr[2],rCBxrDB);
|
||||
|
||||
dotCBDBAB = dot(rCBxrDB,delr[0]);
|
||||
dotDBABCB = dot(rDBxrAB,delr[1]);
|
||||
dotABCBDB = dot(rABxrCB,delr[2]);
|
||||
|
||||
t = rmag[0] * rmag[1] * rmag[2];
|
||||
inv3r = 1.0/t;
|
||||
invs3r[0] = invstheta[1] * inv3r;
|
||||
invs3r[1] = invstheta[2] * inv3r;
|
||||
invs3r[2] = invstheta[0] * inv3r;
|
||||
|
||||
// chi ABCD, CBDA, DBAC
|
||||
// final chi is average of three
|
||||
|
||||
schiABCD = dotCBDBAB * invs3r[0];
|
||||
chiABCD = asin(schiABCD);
|
||||
schiCBDA = dotDBABCB * invs3r[1];
|
||||
chiCBDA = asin(schiCBDA);
|
||||
schiDBAC = dotABCBDB * invs3r[2];
|
||||
chiDBAC = asin(schiDBAC);
|
||||
|
||||
chi = (chiABCD + chiCBDA + chiDBAC) / 3.0;
|
||||
deltachi = chi - chi0[type];
|
||||
d2chi = deltachi * deltachi;
|
||||
|
||||
// energy
|
||||
|
||||
if (EFLAG) eimproper = k0[type]*d2chi;
|
||||
|
||||
// forces
|
||||
// define d(delr)
|
||||
// i = bond AB/CB/DB, j = atom A/B/C/D
|
||||
|
||||
ddelr[0][0] = 1.0;
|
||||
ddelr[0][1] = -1.0;
|
||||
ddelr[0][2] = 0.0;
|
||||
ddelr[0][3] = 0.0;
|
||||
ddelr[1][0] = 0.0;
|
||||
ddelr[1][1] = -1.0;
|
||||
ddelr[1][2] = 1.0;
|
||||
ddelr[1][3] = 0.0;
|
||||
ddelr[2][0] = 0.0;
|
||||
ddelr[2][1] = -1.0;
|
||||
ddelr[2][2] = 0.0;
|
||||
ddelr[2][3] = 1.0;
|
||||
|
||||
// compute d(|r|)/dr and d(1/|r|)/dr for each direction, bond and atom
|
||||
// define d(r) for each r
|
||||
// i = bond AB/CB/DB, j = atom A/B/C/D, k = X/Y/Z
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++) {
|
||||
dr[i][j][k] = delr[i][k] * ddelr[i][j] / rmag[i];
|
||||
dinvr[i][j][k] = -dr[i][j][k] / rmag2[i];
|
||||
}
|
||||
|
||||
// compute d(1 / (|r_AB| * |r_CB| * |r_DB|) / dr
|
||||
// i = atom A/B/C/D, j = X/Y/Z
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
dinv3r[i][j] = rinvmag[1] * (rinvmag[2] * dinvr[0][i][j] +
|
||||
rinvmag[0] * dinvr[2][i][j]) +
|
||||
rinvmag[2] * rinvmag[0] * dinvr[1][i][j];
|
||||
|
||||
// compute d(theta)/d(r) for 3 angles
|
||||
// angleABC
|
||||
|
||||
tt1 = costheta[0] / rmag2[0];
|
||||
tt3 = costheta[0] / rmag2[1];
|
||||
sc1 = 1.0 / sqrt(1.0 - cossqtheta[0]);
|
||||
|
||||
dthetadr[0][0][0] = sc1 * ((tt1 * delr[0][0]) -
|
||||
(delr[1][0] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][0][1] = sc1 * ((tt1 * delr[0][1]) -
|
||||
(delr[1][1] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][0][2] = sc1 * ((tt1 * delr[0][2]) -
|
||||
(delr[1][2] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][1][0] = -sc1 * ((tt1 * delr[0][0]) -
|
||||
(delr[1][0] * rinvmag[0] * rinvmag[1]) +
|
||||
(tt3 * delr[1][0]) -
|
||||
(delr[0][0] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][1][1] = -sc1 * ((tt1 * delr[0][1]) -
|
||||
(delr[1][1] * rinvmag[0] * rinvmag[1]) +
|
||||
(tt3 * delr[1][1]) -
|
||||
(delr[0][1] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][1][2] = -sc1 * ((tt1 * delr[0][2]) -
|
||||
(delr[1][2] * rinvmag[0] * rinvmag[1]) +
|
||||
(tt3 * delr[1][2]) -
|
||||
(delr[0][2] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][2][0] = sc1 * ((tt3 * delr[1][0]) -
|
||||
(delr[0][0] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][2][1] = sc1 * ((tt3 * delr[1][1]) -
|
||||
(delr[0][1] * rinvmag[0] * rinvmag[1]));
|
||||
dthetadr[0][2][2] = sc1 * ((tt3 * delr[1][2]) -
|
||||
(delr[0][2] * rinvmag[0] * rinvmag[1]));
|
||||
|
||||
// angleCBD
|
||||
|
||||
tt1 = costheta[1] / rmag2[1];
|
||||
tt3 = costheta[1] / rmag2[2];
|
||||
sc1 = 1.0 / sqrt(1.0 - cossqtheta[1]);
|
||||
|
||||
dthetadr[1][2][0] = sc1 * ((tt1 * delr[1][0]) -
|
||||
(delr[2][0] * rinvmag[1] * rinvmag[2]));
|
||||
dthetadr[1][2][1] = sc1 * ((tt1 * delr[1][1]) -
|
||||
(delr[2][1] * rinvmag[1] * rinvmag[2]));
|
||||
dthetadr[1][2][2] = sc1 * ((tt1 * delr[1][2]) -
|
||||
(delr[2][2] * rinvmag[1] * rinvmag[2]));
|
||||
dthetadr[1][1][0] = -sc1 * ((tt1 * delr[1][0]) -
|
||||
(delr[2][0] * rinvmag[1] * rinvmag[2]) +
|
||||
(tt3 * delr[2][0]) -
|
||||
(delr[1][0] * rinvmag[2] * rinvmag[1]));
|
||||
dthetadr[1][1][1] = -sc1 * ((tt1 * delr[1][1]) -
|
||||
(delr[2][1] * rinvmag[1] * rinvmag[2]) +
|
||||
(tt3 * delr[2][1]) -
|
||||
(delr[1][1] * rinvmag[2] * rinvmag[1]));
|
||||
dthetadr[1][1][2] = -sc1 * ((tt1 * delr[1][2]) -
|
||||
(delr[2][2] * rinvmag[1] * rinvmag[2]) +
|
||||
(tt3 * delr[2][2]) -
|
||||
(delr[1][2] * rinvmag[2] * rinvmag[1]));
|
||||
dthetadr[1][3][0] = sc1 * ((tt3 * delr[2][0]) -
|
||||
(delr[1][0] * rinvmag[2] * rinvmag[1]));
|
||||
dthetadr[1][3][1] = sc1 * ((tt3 * delr[2][1]) -
|
||||
(delr[1][1] * rinvmag[2] * rinvmag[1]));
|
||||
dthetadr[1][3][2] = sc1 * ((tt3 * delr[2][2]) -
|
||||
(delr[1][2] * rinvmag[2] * rinvmag[1]));
|
||||
|
||||
// angleABD
|
||||
|
||||
tt1 = costheta[2] / rmag2[0];
|
||||
tt3 = costheta[2] / rmag2[2];
|
||||
sc1 = 1.0 / sqrt(1.0 - cossqtheta[2]);
|
||||
|
||||
dthetadr[2][0][0] = sc1 * ((tt1 * delr[0][0]) -
|
||||
(delr[2][0] * rinvmag[0] * rinvmag[2]));
|
||||
dthetadr[2][0][1] = sc1 * ((tt1 * delr[0][1]) -
|
||||
(delr[2][1] * rinvmag[0] * rinvmag[2]));
|
||||
dthetadr[2][0][2] = sc1 * ((tt1 * delr[0][2]) -
|
||||
(delr[2][2] * rinvmag[0] * rinvmag[2]));
|
||||
dthetadr[2][1][0] = -sc1 * ((tt1 * delr[0][0]) -
|
||||
(delr[2][0] * rinvmag[0] * rinvmag[2]) +
|
||||
(tt3 * delr[2][0]) -
|
||||
(delr[0][0] * rinvmag[2] * rinvmag[0]));
|
||||
dthetadr[2][1][1] = -sc1 * ((tt1 * delr[0][1]) -
|
||||
(delr[2][1] * rinvmag[0] * rinvmag[2]) +
|
||||
(tt3 * delr[2][1]) -
|
||||
(delr[0][1] * rinvmag[2] * rinvmag[0]));
|
||||
dthetadr[2][1][2] = -sc1 * ((tt1 * delr[0][2]) -
|
||||
(delr[2][2] * rinvmag[0] * rinvmag[2]) +
|
||||
(tt3 * delr[2][2]) -
|
||||
(delr[0][2] * rinvmag[2] * rinvmag[0]));
|
||||
dthetadr[2][3][0] = sc1 * ((tt3 * delr[2][0]) -
|
||||
(delr[0][0] * rinvmag[2] * rinvmag[0]));
|
||||
dthetadr[2][3][1] = sc1 * ((tt3 * delr[2][1]) -
|
||||
(delr[0][1] * rinvmag[2] * rinvmag[0]));
|
||||
dthetadr[2][3][2] = sc1 * ((tt3 * delr[2][2]) -
|
||||
(delr[0][2] * rinvmag[2] * rinvmag[0]));
|
||||
|
||||
// compute d( 1 / sin(theta))/dr
|
||||
// i = angle, j = atom, k = direction
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
cossin2 = -costheta[i] / sinsqtheta[i];
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
dinvsth[i][j][k] = cossin2 * dthetadr[i][j][k];
|
||||
}
|
||||
|
||||
// compute d(1 / sin(theta) * |r_AB| * |r_CB| * |r_DB|)/dr
|
||||
// i = angle, j = atom
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++) {
|
||||
dinvs3r[0][i][j] = (invstheta[1] * dinv3r[i][j]) +
|
||||
(inv3r * dinvsth[1][i][j]);
|
||||
dinvs3r[1][i][j] = (invstheta[2] * dinv3r[i][j]) +
|
||||
(inv3r * dinvsth[2][i][j]);
|
||||
dinvs3r[2][i][j] = (invstheta[0] * dinv3r[i][j]) +
|
||||
(inv3r * dinvsth[0][i][j]);
|
||||
}
|
||||
|
||||
// drCB(i,j,k), etc
|
||||
// i = vector X'/Y'/Z', j = atom A/B/C/D, k = direction X/Y/Z
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
drCB[i][1][i] = -1.0;
|
||||
drAB[i][1][i] = -1.0;
|
||||
drDB[i][1][i] = -1.0;
|
||||
drDB[i][3][i] = 1.0;
|
||||
drCB[i][2][i] = 1.0;
|
||||
drAB[i][0][i] = 1.0;
|
||||
}
|
||||
|
||||
// d((r_CB x r_DB) dot r_AB)
|
||||
// r_CB x d(r_DB)
|
||||
// d(r_CB) x r_DB
|
||||
// (r_CB x d(r_DB)) + (d(r_CB) x r_DB)
|
||||
// (r_CB x d(r_DB)) + (d(r_CB) x r_DB) dot r_AB
|
||||
// d(r_AB) dot (r_CB x r_DB)
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++) {
|
||||
cross(delr[1],drDB[i][j],rCBxdrDB);
|
||||
cross(drCB[i][j],delr[2],drCBxrDB);
|
||||
for (k = 0; k < 3; k++) dd[k] = rCBxdrDB[k] + drCBxrDB[k];
|
||||
dot1 = dot(dd,delr[0]);
|
||||
dot2 = dot(rCBxrDB,drAB[i][j]);
|
||||
fdot[0][j][i] = dot1 + dot2;
|
||||
}
|
||||
|
||||
// d((r_DB x r_AB) dot r_CB)
|
||||
// r_DB x d(r_AB)
|
||||
// d(r_DB) x r_AB
|
||||
// (r_DB x d(r_AB)) + (d(r_DB) x r_AB)
|
||||
// (r_DB x d(r_AB)) + (d(r_DB) x r_AB) dot r_CB
|
||||
// d(r_CB) dot (r_DB x r_AB)
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++) {
|
||||
cross(delr[2],drAB[i][j],rDBxdrAB);
|
||||
cross(drDB[i][j],delr[0],drDBxrAB);
|
||||
for (k = 0; k < 3; k++) dd[k] = rDBxdrAB[k] + drDBxrAB[k];
|
||||
dot1 = dot(dd,delr[1]);
|
||||
dot2 = dot(rDBxrAB,drCB[i][j]);
|
||||
fdot[1][j][i] = dot1 + dot2;
|
||||
}
|
||||
|
||||
// d((r_AB x r_CB) dot r_DB)
|
||||
// r_AB x d(r_CB)
|
||||
// d(r_AB) x r_CB
|
||||
// (r_AB x d(r_CB)) + (d(r_AB) x r_CB)
|
||||
// (r_AB x d(r_CB)) + (d(r_AB) x r_CB) dot r_DB
|
||||
// d(r_DB) dot (r_AB x r_CB)
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++) {
|
||||
cross(delr[0],drCB[i][j],rABxdrCB);
|
||||
cross(drAB[i][j],delr[1],drABxrCB);
|
||||
for (k = 0; k < 3; k++) dd[k] = rABxdrCB[k] + drABxrCB[k];
|
||||
dot1 = dot(dd,delr[2]);
|
||||
dot2 = dot(rABxrCB,drDB[i][j]);
|
||||
fdot[2][j][i] = dot1 + dot2;
|
||||
}
|
||||
|
||||
// force on each atom
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++) {
|
||||
ftmp = (fdot[0][i][j] * invs3r[0]) +
|
||||
(dinvs3r[0][i][j] * dotCBDBAB);
|
||||
dchi[0][i][j] = ftmp / cos(chiABCD);
|
||||
ftmp = (fdot[1][i][j] * invs3r[1]) +
|
||||
(dinvs3r[1][i][j] * dotDBABCB);
|
||||
dchi[1][i][j] = ftmp / cos(chiCBDA);
|
||||
ftmp = (fdot[2][i][j] * invs3r[2]) +
|
||||
(dinvs3r[2][i][j] * dotABCBDB);
|
||||
dchi[2][i][j] = ftmp / cos(chiDBAC);
|
||||
dtotalchi[i][j] = (dchi[0][i][j]+dchi[1][i][j]+dchi[2][i][j]) / 3.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] = -2.0*k0[type] * deltachi*dtotalchi[i][j];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += fabcd[0][0];
|
||||
f[i1][1] += fabcd[0][1];
|
||||
f[i1][2] += fabcd[0][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += fabcd[1][0];
|
||||
f[i2][1] += fabcd[1][1];
|
||||
f[i2][2] += fabcd[1][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += fabcd[2][0];
|
||||
f[i3][1] += fabcd[2][1];
|
||||
f[i3][2] += fabcd[2][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += fabcd[3][0];
|
||||
f[i4][1] += fabcd[3][1];
|
||||
f[i4][2] += fabcd[3][2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,
|
||||
fabcd[0],fabcd[2],fabcd[3],
|
||||
delr[0][0],delr[0][1],delr[0][2],
|
||||
delr[1][0],delr[1][1],delr[1][2],
|
||||
delr[2][0]-delr[1][0],delr[2][1]-delr[1][1],
|
||||
delr[2][2]-delr[1][2],thr);
|
||||
}
|
||||
|
||||
// compute angle-angle interactions
|
||||
angleangle_thr<EVFLAG, EFLAG, NEWTON_BOND>(nfrom,nto,thr);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
angle-angle interactions within improper
|
||||
------------------------------------------------------------------------- */
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperClass2OMP::angleangle_thr(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,i,j,k,n,type;
|
||||
double eimproper;
|
||||
double delxAB,delyAB,delzAB,rABmag2,rAB;
|
||||
double delxBC,delyBC,delzBC,rBCmag2,rBC;
|
||||
double delxBD,delyBD,delzBD,rBDmag2,rBD;
|
||||
double costhABC,thetaABC,costhABD;
|
||||
double thetaABD,costhCBD,thetaCBD,dthABC,dthCBD,dthABD;
|
||||
double sc1,t1,t3,r12;
|
||||
double dthetadr[3][4][3],fabcd[4][3];
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
// difference vectors
|
||||
|
||||
delxAB = x[i1][0] - x[i2][0];
|
||||
delyAB = x[i1][1] - x[i2][1];
|
||||
delzAB = x[i1][2] - x[i2][2];
|
||||
|
||||
delxBC = x[i3][0] - x[i2][0];
|
||||
delyBC = x[i3][1] - x[i2][1];
|
||||
delzBC = x[i3][2] - x[i2][2];
|
||||
|
||||
delxBD = x[i4][0] - x[i2][0];
|
||||
delyBD = x[i4][1] - x[i2][1];
|
||||
delzBD = x[i4][2] - x[i2][2];
|
||||
|
||||
// bond lengths
|
||||
|
||||
rABmag2 = delxAB*delxAB + delyAB*delyAB + delzAB*delzAB;
|
||||
rAB = sqrt(rABmag2);
|
||||
rBCmag2 = delxBC*delxBC + delyBC*delyBC + delzBC*delzBC;
|
||||
rBC = sqrt(rBCmag2);
|
||||
rBDmag2 = delxBD*delxBD + delyBD*delyBD + delzBD*delzBD;
|
||||
rBD = sqrt(rBDmag2);
|
||||
|
||||
// angle ABC, ABD, CBD
|
||||
|
||||
costhABC = (delxAB*delxBC + delyAB*delyBC + delzAB*delzBC) / (rAB * rBC);
|
||||
if (costhABC > 1.0) costhABC = 1.0;
|
||||
if (costhABC < -1.0) costhABC = -1.0;
|
||||
thetaABC = acos(costhABC);
|
||||
|
||||
costhABD = (delxAB*delxBD + delyAB*delyBD + delzAB*delzBD) / (rAB * rBD);
|
||||
if (costhABD > 1.0) costhABD = 1.0;
|
||||
if (costhABD < -1.0) costhABD = -1.0;
|
||||
thetaABD = acos(costhABD);
|
||||
|
||||
costhCBD = (delxBC*delxBD + delyBC*delyBD + delzBC*delzBD) /(rBC * rBD);
|
||||
if (costhCBD > 1.0) costhCBD = 1.0;
|
||||
if (costhCBD < -1.0) costhCBD = -1.0;
|
||||
thetaCBD = acos(costhCBD);
|
||||
|
||||
dthABC = thetaABC - aa_theta0_1[type];
|
||||
dthABD = thetaABD - aa_theta0_2[type];
|
||||
dthCBD = thetaCBD - aa_theta0_3[type];
|
||||
|
||||
// energy
|
||||
|
||||
if (EFLAG) eimproper = aa_k2[type] * dthABC * dthABD +
|
||||
aa_k1[type] * dthABC * dthCBD +
|
||||
aa_k3[type] * dthABD * dthCBD;
|
||||
|
||||
// d(theta)/d(r) array
|
||||
// angle i, atom j, coordinate k
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
for (k = 0; k < 3; k++)
|
||||
dthetadr[i][j][k] = 0.0;
|
||||
|
||||
// angle ABC
|
||||
|
||||
sc1 = sqrt(1.0/(1.0 - costhABC*costhABC));
|
||||
t1 = costhABC / rABmag2;
|
||||
t3 = costhABC / rBCmag2;
|
||||
r12 = 1.0 / (rAB * rBC);
|
||||
|
||||
dthetadr[0][0][0] = sc1 * ((t1 * delxAB) - (delxBC * r12));
|
||||
dthetadr[0][0][1] = sc1 * ((t1 * delyAB) - (delyBC * r12));
|
||||
dthetadr[0][0][2] = sc1 * ((t1 * delzAB) - (delzBC * r12));
|
||||
dthetadr[0][1][0] = sc1 * ((-t1 * delxAB) + (delxBC * r12) +
|
||||
(-t3 * delxBC) + (delxAB * r12));
|
||||
dthetadr[0][1][1] = sc1 * ((-t1 * delyAB) + (delyBC * r12) +
|
||||
(-t3 * delyBC) + (delyAB * r12));
|
||||
dthetadr[0][1][2] = sc1 * ((-t1 * delzAB) + (delzBC * r12) +
|
||||
(-t3 * delzBC) + (delzAB * r12));
|
||||
dthetadr[0][2][0] = sc1 * ((t3 * delxBC) - (delxAB * r12));
|
||||
dthetadr[0][2][1] = sc1 * ((t3 * delyBC) - (delyAB * r12));
|
||||
dthetadr[0][2][2] = sc1 * ((t3 * delzBC) - (delzAB * r12));
|
||||
|
||||
// angle CBD
|
||||
|
||||
sc1 = sqrt(1.0/(1.0 - costhCBD*costhCBD));
|
||||
t1 = costhCBD / rBCmag2;
|
||||
t3 = costhCBD / rBDmag2;
|
||||
r12 = 1.0 / (rBC * rBD);
|
||||
|
||||
dthetadr[1][2][0] = sc1 * ((t1 * delxBC) - (delxBD * r12));
|
||||
dthetadr[1][2][1] = sc1 * ((t1 * delyBC) - (delyBD * r12));
|
||||
dthetadr[1][2][2] = sc1 * ((t1 * delzBC) - (delzBD * r12));
|
||||
dthetadr[1][1][0] = sc1 * ((-t1 * delxBC) + (delxBD * r12) +
|
||||
(-t3 * delxBD) + (delxBC * r12));
|
||||
dthetadr[1][1][1] = sc1 * ((-t1 * delyBC) + (delyBD * r12) +
|
||||
(-t3 * delyBD) + (delyBC * r12));
|
||||
dthetadr[1][1][2] = sc1 * ((-t1 * delzBC) + (delzBD * r12) +
|
||||
(-t3 * delzBD) + (delzBC * r12));
|
||||
dthetadr[1][3][0] = sc1 * ((t3 * delxBD) - (delxBC * r12));
|
||||
dthetadr[1][3][1] = sc1 * ((t3 * delyBD) - (delyBC * r12));
|
||||
dthetadr[1][3][2] = sc1 * ((t3 * delzBD) - (delzBC * r12));
|
||||
|
||||
// angle ABD
|
||||
|
||||
sc1 = sqrt(1.0/(1.0 - costhABD*costhABD));
|
||||
t1 = costhABD / rABmag2;
|
||||
t3 = costhABD / rBDmag2;
|
||||
r12 = 1.0 / (rAB * rBD);
|
||||
|
||||
dthetadr[2][0][0] = sc1 * ((t1 * delxAB) - (delxBD * r12));
|
||||
dthetadr[2][0][1] = sc1 * ((t1 * delyAB) - (delyBD * r12));
|
||||
dthetadr[2][0][2] = sc1 * ((t1 * delzAB) - (delzBD * r12));
|
||||
dthetadr[2][1][0] = sc1 * ((-t1 * delxAB) + (delxBD * r12) +
|
||||
(-t3 * delxBD) + (delxAB * r12));
|
||||
dthetadr[2][1][1] = sc1 * ((-t1 * delyAB) + (delyBD * r12) +
|
||||
(-t3 * delyBD) + (delyAB * r12));
|
||||
dthetadr[2][1][2] = sc1 * ((-t1 * delzAB) + (delzBD * r12) +
|
||||
(-t3 * delzBD) + (delzAB * r12));
|
||||
dthetadr[2][3][0] = sc1 * ((t3 * delxBD) - (delxAB * r12));
|
||||
dthetadr[2][3][1] = sc1 * ((t3 * delyBD) - (delyAB * r12));
|
||||
dthetadr[2][3][2] = sc1 * ((t3 * delzBD) - (delzAB * r12));
|
||||
|
||||
// angleangle forces
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
fabcd[i][j] = -
|
||||
((aa_k1[type] *
|
||||
(dthABC*dthetadr[1][i][j] + dthCBD*dthetadr[0][i][j])) +
|
||||
(aa_k2[type] *
|
||||
(dthABC*dthetadr[2][i][j] + dthABD*dthetadr[0][i][j])) +
|
||||
(aa_k3[type] *
|
||||
(dthABD*dthetadr[1][i][j] + dthCBD*dthetadr[2][i][j])));
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += fabcd[0][0];
|
||||
f[i1][1] += fabcd[0][1];
|
||||
f[i1][2] += fabcd[0][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += fabcd[1][0];
|
||||
f[i2][1] += fabcd[1][1];
|
||||
f[i2][2] += fabcd[1][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += fabcd[2][0];
|
||||
f[i3][1] += fabcd[2][1];
|
||||
f[i3][2] += fabcd[2][2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += fabcd[3][0];
|
||||
f[i4][1] += fabcd[3][1];
|
||||
f[i4][2] += fabcd[3][2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,
|
||||
fabcd[0],fabcd[2],fabcd[3],delxAB,delyAB,delzAB,
|
||||
delxBC,delyBC,delzBC,delxBD,delyBD,delzBD,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(class2/omp,ImproperClass2OMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_CLASS2_OMP_H
|
||||
#define LMP_IMPROPER_CLASS2_OMP_H
|
||||
|
||||
#include "improper_class2.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperClass2OMP : public ImproperClass2, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperClass2OMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void angleangle_thr(int, int, ThrData * const thr);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,267 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_cossq_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperCossqOMP::ImproperCossqOMP(class LAMMPS *lmp)
|
||||
: ImproperCossq(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCossqOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperCossqOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
|
||||
double eimproper,f1[3],f2[3],f3[3],f4[3];
|
||||
double rjisq, rji, rlksq, rlk, cosphi, angfac;
|
||||
double cjiji, clkji, clklk, cfact1, cfact2, cfact3;
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
/* separation vector between i1 and i2, (i2-i1) */
|
||||
vb1x = x[i2][0] - x[i1][0];
|
||||
vb1y = x[i2][1] - x[i1][1];
|
||||
vb1z = x[i2][2] - x[i1][2];
|
||||
rjisq = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z ;
|
||||
rji = sqrt(rjisq);
|
||||
|
||||
/* separation vector between i2 and i3 (i3-i2) */
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
/* separation vector between i3 and i4, (i4-i3) */
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
rlksq = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z ;
|
||||
rlk = sqrt(rlksq);
|
||||
|
||||
cosphi = (vb3x*vb1x + vb3y*vb1y + vb3z*vb1z)/(rji * rlk);
|
||||
|
||||
/* Check that cos(phi) is in the correct limits. */
|
||||
if (cosphi > 1.0 + TOLERANCE || cosphi < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Improper problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
|
||||
|
||||
/* Apply corrections to round-off errors. */
|
||||
if (cosphi > 1.0) cosphi -= SMALL;
|
||||
if (cosphi < -1.0) cosphi += SMALL;
|
||||
|
||||
/* Calculate the angle: */
|
||||
double torangle = acos(cosphi);
|
||||
cosphi = cos(torangle - chi[type]);
|
||||
|
||||
if (EFLAG) eimproper = 0.5 * k[type] * cosphi * cosphi;
|
||||
|
||||
/*
|
||||
printf("The tags: %d-%d-%d-%d, of type %d .\n",atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4],type);
|
||||
printf("The ji vector: %f, %f, %f.\nThe lk vector: %f, %f, %f.\n", vb1x,vb1y,vb1z,vb3x,vb3y,vb3z);
|
||||
printf("The cosine of the angle: %-1.16e.\n", cosphi);
|
||||
printf("The energy of the improper: %-1.16e with prefactor %-1.16e.\n", eimproper, 0.5*k[type]);
|
||||
*/
|
||||
|
||||
/* Work out forces. */
|
||||
angfac = - k[type] * cosphi;
|
||||
|
||||
cjiji = rjisq;
|
||||
clklk = rlksq;
|
||||
/*CLKJI = RXLK * RXJI + RYLK * RYJI + RZLK * RZJI */
|
||||
clkji = vb3x*vb1x + vb3y*vb1y + vb3z*vb1z;
|
||||
|
||||
/*CFACT1 = CLKLK * CJIJI
|
||||
CFACT1 = SQRT(CFACT1)
|
||||
CFACT1 = ANGFAC / CFACT1*/
|
||||
cfact1 = angfac / sqrt(clklk * cjiji);
|
||||
/*CFACT2 = CLKJI / CLKLK*/
|
||||
cfact2 = clkji / clklk;
|
||||
/*CFACT3 = CLKJI / CJIJI*/
|
||||
cfact3 = clkji / cjiji;
|
||||
|
||||
/*FIX = -RXLK + CFACT3 * RXJI
|
||||
FIY = -RYLK + CFACT3 * RYJI
|
||||
FIZ = -RZLK + CFACT3 * RZJI*/
|
||||
f1[0] = - vb3x + cfact3 * vb1x;
|
||||
f1[1] = - vb3y + cfact3 * vb1y;
|
||||
f1[2] = - vb3z + cfact3 * vb1z;
|
||||
|
||||
/*FJX = -FIX
|
||||
FJY = -FIY
|
||||
FJZ = -FIZ*/
|
||||
f2[0] = - f1[0];
|
||||
f2[1] = - f1[1];
|
||||
f2[2] = - f1[2];
|
||||
|
||||
/*FKX = CFACT2 * RXLK - RXJI
|
||||
FKY = CFACT2 * RYLK - RYJI
|
||||
FKZ = CFACT2 * RZLK - RZJI*/
|
||||
f3[0] = cfact2 * vb3x - vb1x;
|
||||
f3[1] = cfact2 * vb3y - vb1y;
|
||||
f3[2] = cfact2 * vb3z - vb1z;
|
||||
|
||||
/*FLX = -FKX
|
||||
FLY = -FKY
|
||||
FLZ = -FKZ*/
|
||||
f4[0] = - f3[0];
|
||||
f4[1] = - f3[1];
|
||||
f4[2] = - f3[2];
|
||||
|
||||
/*FIX = FIX * CFACT1
|
||||
FIY = FIY * CFACT1
|
||||
FIZ = FIZ * CFACT1*/
|
||||
f1[0] *= cfact1;
|
||||
f1[1] *= cfact1;
|
||||
f1[2] *= cfact1;
|
||||
|
||||
/*FJX = FJX * CFACT1
|
||||
FJY = FJY * CFACT1
|
||||
FJZ = FJZ * CFACT1*/
|
||||
f2[0] *= cfact1;
|
||||
f2[1] *= cfact1;
|
||||
f2[2] *= cfact1;
|
||||
|
||||
/*FKX = FKX * CFACT1
|
||||
FKY = FKY * CFACT1
|
||||
FKZ = FKZ * CFACT1*/
|
||||
f3[0] *= cfact1;
|
||||
f3[1] *= cfact1;
|
||||
f3[2] *= cfact1;
|
||||
|
||||
/*FLX = FLX * CFACT1
|
||||
FLY = FLY * CFACT1
|
||||
FLZ = FLZ * CFACT1*/
|
||||
f4[0] *= cfact1;
|
||||
f4[1] *= cfact1;
|
||||
f4[2] *= cfact1;
|
||||
|
||||
/* Apply force to each of 4 atoms */
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,f1,f3,f4,
|
||||
-vb1x,-vb1y,-vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(cossq/omp,ImproperCossqOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_COSSQ_OMP_H
|
||||
#define LMP_IMPROPER_COSSQ_OMP_H
|
||||
|
||||
#include "improper_cossq.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperCossqOMP : public ImproperCossq, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperCossqOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,298 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_cvff_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperCvffOMP::ImproperCvffOMP(class LAMMPS *lmp)
|
||||
: ImproperCvff(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperCvffOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperCvffOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,m,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||
double eimproper,f1[3],f2[3],f3[3],f4[3];
|
||||
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
|
||||
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
|
||||
double c2mag,sc1,sc2,s1,s2,s12,c,p,pd,rc2,a,a11,a22;
|
||||
double a33,a12,a13,a23,sx2,sy2,sz2;
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb2xm = -vb2x;
|
||||
vb2ym = -vb2y;
|
||||
vb2zm = -vb2z;
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
// c0 calculation
|
||||
|
||||
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
rb1 = sqrt(sb1);
|
||||
rb3 = sqrt(sb3);
|
||||
|
||||
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
|
||||
|
||||
// 1st and 2nd angle
|
||||
|
||||
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
|
||||
b1mag = sqrt(b1mag2);
|
||||
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
|
||||
b2mag = sqrt(b2mag2);
|
||||
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
|
||||
b3mag = sqrt(b3mag2);
|
||||
|
||||
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
|
||||
r12c1 = 1.0 / (b1mag*b2mag);
|
||||
c1mag = ctmp * r12c1;
|
||||
|
||||
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
|
||||
r12c2 = 1.0 / (b2mag*b3mag);
|
||||
c2mag = ctmp * r12c2;
|
||||
|
||||
// cos and sin of 2 angles and final c
|
||||
|
||||
sc1 = sqrt(1.0 - c1mag*c1mag);
|
||||
if (sc1 < SMALL) sc1 = SMALL;
|
||||
sc1 = 1.0/sc1;
|
||||
|
||||
sc2 = sqrt(1.0 - c2mag*c2mag);
|
||||
if (sc2 < SMALL) sc2 = SMALL;
|
||||
sc2 = 1.0/sc2;
|
||||
|
||||
s1 = sc1 * sc1;
|
||||
s2 = sc2 * sc2;
|
||||
s12 = sc1 * sc2;
|
||||
c = (c0 + c1mag*c2mag) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Improper problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
// force & energy
|
||||
// p = 1 + cos(n*phi) for d = 1
|
||||
// p = 1 - cos(n*phi) for d = -1
|
||||
// pd = dp/dc / 2
|
||||
|
||||
m = multiplicity[type];
|
||||
|
||||
if (m == 2) {
|
||||
p = 2.0*c*c;
|
||||
pd = 2.0*c;
|
||||
} else if (m == 3) {
|
||||
rc2 = c*c;
|
||||
p = (4.0*rc2-3.0)*c + 1.0;
|
||||
pd = 6.0*rc2 - 1.5;
|
||||
} else if (m == 4) {
|
||||
rc2 = c*c;
|
||||
p = 8.0*(rc2-1)*rc2 + 2.0;
|
||||
pd = (16.0*rc2-8.0)*c;
|
||||
} else if (m == 6) {
|
||||
rc2 = c*c;
|
||||
p = ((32.0*rc2-48.0)*rc2 + 18.0)*rc2;
|
||||
pd = (96.0*(rc2-1.0)*rc2 + 18.0)*c;
|
||||
} else if (m == 1) {
|
||||
p = c + 1.0;
|
||||
pd = 0.5;
|
||||
} else if (m == 5) {
|
||||
rc2 = c*c;
|
||||
p = ((16.0*rc2-20.0)*rc2 + 5.0)*c + 1.0;
|
||||
pd = (40.0*rc2-30.0)*rc2 + 2.5;
|
||||
} else if (m == 0) {
|
||||
p = 2.0;
|
||||
pd = 0.0;
|
||||
}
|
||||
|
||||
if (sign[type] == -1) {
|
||||
p = 2.0 - p;
|
||||
pd = -pd;
|
||||
}
|
||||
|
||||
if (EFLAG) eimproper = k[type]*p;
|
||||
|
||||
a = 2.0 * k[type] * pd;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = c*sb1*s1;
|
||||
a22 = -sb2*(2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = c*sb3*s2;
|
||||
a12 = -r12c1*(c1mag*c*s1 + c2mag*s12);
|
||||
a13 = -rb1*rb3*s12;
|
||||
a23 = r12c2*(c2mag*c*s2 + c1mag*s12);
|
||||
|
||||
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
|
||||
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
|
||||
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
|
||||
|
||||
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
|
||||
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
|
||||
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
|
||||
|
||||
f2[0] = -sx2 - f1[0];
|
||||
f2[1] = -sy2 - f1[1];
|
||||
f2[2] = -sz2 - f1[2];
|
||||
|
||||
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
|
||||
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
|
||||
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
|
||||
|
||||
f3[0] = sx2 - f4[0];
|
||||
f3[1] = sy2 - f4[1];
|
||||
f3[2] = sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(cvff/omp,ImproperCvffOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_CVFF_OMP_H
|
||||
#define LMP_IMPROPER_CVFF_OMP_H
|
||||
|
||||
#include "improper_cvff.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperCvffOMP : public ImproperCvff, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperCvffOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,240 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_harmonic_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperHarmonicOMP::ImproperHarmonicOMP(class LAMMPS *lmp)
|
||||
: ImproperHarmonic(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperHarmonicOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperHarmonicOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
|
||||
double eimproper,f1[3],f2[3],f3[3],f4[3];
|
||||
double ss1,ss2,ss3,r1,r2,r3,c0,c1,c2,s1,s2;
|
||||
double s12,c,s,domega,a,a11,a22,a33,a12,a13,a23;
|
||||
double sx2,sy2,sz2;
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
// geometry of 4-body
|
||||
|
||||
vb1x = x[i1][0] - x[i2][0];
|
||||
vb1y = x[i1][1] - x[i2][1];
|
||||
vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0];
|
||||
vb2y = x[i3][1] - x[i2][1];
|
||||
vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0];
|
||||
vb3y = x[i4][1] - x[i3][1];
|
||||
vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
ss1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
|
||||
ss2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
|
||||
ss3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
|
||||
|
||||
r1 = sqrt(ss1);
|
||||
r2 = sqrt(ss2);
|
||||
r3 = sqrt(ss3);
|
||||
|
||||
// sin and cos of angle
|
||||
|
||||
c0 = (vb1x * vb3x + vb1y * vb3y + vb1z * vb3z) * r1 * r3;
|
||||
c1 = (vb1x * vb2x + vb1y * vb2y + vb1z * vb2z) * r1 * r2;
|
||||
c2 = -(vb3x * vb2x + vb3y * vb2y + vb3z * vb2z) * r3 * r2;
|
||||
|
||||
s1 = 1.0 - c1*c1;
|
||||
if (s1 < SMALL) s1 = SMALL;
|
||||
s1 = 1.0 / s1;
|
||||
|
||||
s2 = 1.0 - c2*c2;
|
||||
if (s2 < SMALL) s2 = SMALL;
|
||||
s2 = 1.0 / s2;
|
||||
|
||||
s12 = sqrt(s1*s2);
|
||||
c = (c1*c2 + c0) * s12;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Improper problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) c = 1.0;
|
||||
if (c < -1.0) c = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
|
||||
// force & energy
|
||||
|
||||
domega = acos(c) - chi[type];
|
||||
a = k[type] * domega;
|
||||
|
||||
if (EFLAG) eimproper = a*domega;
|
||||
|
||||
a = -a * 2.0/s;
|
||||
c = c * a;
|
||||
s12 = s12 * a;
|
||||
a11 = c*ss1*s1;
|
||||
a22 = -ss2 * (2.0*c0*s12 - c*(s1+s2));
|
||||
a33 = c*ss3*s2;
|
||||
a12 = -r1*r2*(c1*c*s1 + c2*s12);
|
||||
a13 = -r1*r3*s12;
|
||||
a23 = r2*r3*(c2*c*s2 + c1*s12);
|
||||
|
||||
sx2 = a22*vb2x + a23*vb3x + a12*vb1x;
|
||||
sy2 = a22*vb2y + a23*vb3y + a12*vb1y;
|
||||
sz2 = a22*vb2z + a23*vb3z + a12*vb1z;
|
||||
|
||||
f1[0] = a12*vb2x + a13*vb3x + a11*vb1x;
|
||||
f1[1] = a12*vb2y + a13*vb3y + a11*vb1y;
|
||||
f1[2] = a12*vb2z + a13*vb3z + a11*vb1z;
|
||||
|
||||
f2[0] = -sx2 - f1[0];
|
||||
f2[1] = -sy2 - f1[1];
|
||||
f2[2] = -sz2 - f1[2];
|
||||
|
||||
f4[0] = a23*vb2x + a33*vb3x + a13*vb1x;
|
||||
f4[1] = a23*vb2y + a33*vb3y + a13*vb1y;
|
||||
f4[2] = a23*vb2z + a33*vb3z + a13*vb1z;
|
||||
|
||||
f3[0] = sx2 - f4[0];
|
||||
f3[1] = sy2 - f4[1];
|
||||
f3[2] = sz2 - f4[2];
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0];
|
||||
f[i1][1] += f1[1];
|
||||
f[i1][2] += f1[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f2[0];
|
||||
f[i2][1] += f2[1];
|
||||
f[i2][2] += f2[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f3[0];
|
||||
f[i3][1] += f3[1];
|
||||
f[i3][2] += f3[2];
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0];
|
||||
f[i4][1] += f4[1];
|
||||
f[i4][2] += f4[2];
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(harmonic/omp,ImproperHarmonicOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_HARMONIC_OMP_H
|
||||
#define LMP_IMPROPER_HARMONIC_OMP_H
|
||||
|
||||
#include "improper_harmonic.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperHarmonicOMP : public ImproperHarmonic, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperHarmonicOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,261 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_ring_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperRingOMP::ImproperRingOMP(class LAMMPS *lmp)
|
||||
: ImproperRing(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperRingOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperRingOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
/* Be careful!: "chi" is the equilibrium angle in radians. */
|
||||
int i1,i2,i3,i4,n,type;
|
||||
|
||||
double eimproper;
|
||||
|
||||
/* Compatibility variables. */
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
|
||||
double f1[3], f3[3], f4[3];
|
||||
|
||||
/* Actual computation variables. */
|
||||
int at1[3], at2[3], at3[3], icomb;
|
||||
double bvec1x[3], bvec1y[3], bvec1z[3],
|
||||
bvec2x[3], bvec2y[3], bvec2z[3],
|
||||
bvec1n[3], bvec2n[3], bend_angle[3];
|
||||
double angle_summer, angfac, cfact1, cfact2, cfact3;
|
||||
double cjiji, ckjji, ckjkj, fix, fiy, fiz, fjx, fjy, fjz, fkx, fky, fkz;
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
/* A description of the potential can be found in
|
||||
Macromolecules 35, pp. 1463-1472 (2002). */
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
/* Take the ids of the atoms contributing to the improper potential. */
|
||||
i1 = improperlist[n][0]; /* Atom "1" of Figure 1 from the above reference.*/
|
||||
i2 = improperlist[n][1]; /* Atom "2" ... */
|
||||
i3 = improperlist[n][2]; /* Atom "3" ... */
|
||||
i4 = improperlist[n][3]; /* Atom "9" ... */
|
||||
type = improperlist[n][4];
|
||||
|
||||
/* Calculate the necessary variables for LAMMPS implementation.
|
||||
if (evflag) ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
|
||||
Although, they are irrelevant to the calculation of the potential, we keep
|
||||
them for maximal compatibility. */
|
||||
vb1x = x[i1][0] - x[i2][0]; vb1y = x[i1][1] - x[i2][1]; vb1z = x[i1][2] - x[i2][2];
|
||||
|
||||
vb2x = x[i3][0] - x[i2][0]; vb2y = x[i3][1] - x[i2][1]; vb2z = x[i3][2] - x[i2][2];
|
||||
|
||||
vb3x = x[i4][0] - x[i3][0]; vb3y = x[i4][1] - x[i3][1]; vb3z = x[i4][2] - x[i3][2];
|
||||
|
||||
|
||||
/* Pass the atom tags to form the necessary combinations. */
|
||||
at1[0] = i1; at2[0] = i2; at3[0] = i4; /* ids: 1-2-9 */
|
||||
at1[1] = i1; at2[1] = i2; at3[1] = i3; /* ids: 1-2-3 */
|
||||
at1[2] = i4; at2[2] = i2; at3[2] = i3; /* ids: 9-2-3 */
|
||||
|
||||
|
||||
/* Initialize the sum of the angles differences. */
|
||||
angle_summer = 0.0;
|
||||
/* Take a loop over the three angles, defined by each triad: */
|
||||
for (icomb = 0; icomb < 3; icomb ++) {
|
||||
|
||||
/* Bond vector connecting the first and the second atom. */
|
||||
bvec1x[icomb] = x[at2[icomb]][0] - x[at1[icomb]][0];
|
||||
bvec1y[icomb] = x[at2[icomb]][1] - x[at1[icomb]][1];
|
||||
bvec1z[icomb] = x[at2[icomb]][2] - x[at1[icomb]][2];
|
||||
/* also calculate the norm of the vector: */
|
||||
bvec1n[icomb] = sqrt( bvec1x[icomb]*bvec1x[icomb]
|
||||
+ bvec1y[icomb]*bvec1y[icomb]
|
||||
+ bvec1z[icomb]*bvec1z[icomb]);
|
||||
/* Bond vector connecting the second and the third atom. */
|
||||
bvec2x[icomb] = x[at3[icomb]][0] - x[at2[icomb]][0];
|
||||
bvec2y[icomb] = x[at3[icomb]][1] - x[at2[icomb]][1];
|
||||
bvec2z[icomb] = x[at3[icomb]][2] - x[at2[icomb]][2];
|
||||
/* also calculate the norm of the vector: */
|
||||
bvec2n[icomb] = sqrt( bvec2x[icomb]*bvec2x[icomb]
|
||||
+ bvec2y[icomb]*bvec2y[icomb]
|
||||
+ bvec2z[icomb]*bvec2z[icomb]);
|
||||
|
||||
/* Calculate the bending angle of the atom triad: */
|
||||
bend_angle[icomb] = ( bvec2x[icomb]*bvec1x[icomb]
|
||||
+ bvec2y[icomb]*bvec1y[icomb]
|
||||
+ bvec2z[icomb]*bvec1z[icomb]);
|
||||
bend_angle[icomb] /= (bvec1n[icomb] * bvec2n[icomb]);
|
||||
if (bend_angle[icomb] > 1.0) bend_angle[icomb] -= SMALL;
|
||||
if (bend_angle[icomb] < -1.0) bend_angle[icomb] += SMALL;
|
||||
|
||||
/* Append the current angle to the sum of angle differences. */
|
||||
angle_summer += (bend_angle[icomb] - chi[type]);
|
||||
}
|
||||
if (EFLAG) eimproper = (1.0/6.0) *k[type] * pow(angle_summer,6.0);
|
||||
/*
|
||||
printf("The tags: %d-%d-%d-%d, of type %d .\n",atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4],type);
|
||||
// printf("The coordinates of the first: %f, %f, %f.\n", x[i1][0], x[i1][1], x[i1][2]);
|
||||
// printf("The coordinates of the second: %f, %f, %f.\n", x[i2][0], x[i2][1], x[i2][2]);
|
||||
// printf("The coordinates of the third: %f, %f, %f.\n", x[i3][0], x[i3][1], x[i3][2]);
|
||||
// printf("The coordinates of the fourth: %f, %f, %f.\n", x[i4][0], x[i4][1], x[i4][2]);
|
||||
printf("The angles are: %f / %f / %f equilibrium: %f.\n", bend_angle[0], bend_angle[1], bend_angle[2],chi[type]);
|
||||
printf("The energy of the improper: %f with prefactor %f.\n", eimproper,(1.0/6.0)*k[type]);
|
||||
printf("The sum of the angles: %f.\n", angle_summer);
|
||||
*/
|
||||
|
||||
/* Force calculation acting on all atoms.
|
||||
Calculate the derivatives of the potential. */
|
||||
angfac = k[type] * pow(angle_summer,5.0);
|
||||
|
||||
f1[0] = 0.0; f1[1] = 0.0; f1[2] = 0.0;
|
||||
f3[0] = 0.0; f3[1] = 0.0; f3[2] = 0.0;
|
||||
f4[0] = 0.0; f4[1] = 0.0; f4[2] = 0.0;
|
||||
|
||||
/* Take a loop over the three angles, defined by each triad: */
|
||||
for (icomb = 0; icomb < 3; icomb ++)
|
||||
{
|
||||
/* Calculate the squares of the distances. */
|
||||
cjiji = bvec1n[icomb] * bvec1n[icomb]; ckjkj = bvec2n[icomb] * bvec2n[icomb];
|
||||
|
||||
ckjji = bvec2x[icomb] * bvec1x[icomb]
|
||||
+ bvec2y[icomb] * bvec1y[icomb]
|
||||
+ bvec2z[icomb] * bvec1z[icomb] ;
|
||||
|
||||
cfact1 = angfac / (sqrt(ckjkj * cjiji));
|
||||
cfact2 = ckjji / ckjkj;
|
||||
cfact3 = ckjji / cjiji;
|
||||
|
||||
/* Calculate the force acted on the thrid atom of the angle. */
|
||||
fkx = cfact2 * bvec2x[icomb] - bvec1x[icomb];
|
||||
fky = cfact2 * bvec2y[icomb] - bvec1y[icomb];
|
||||
fkz = cfact2 * bvec2z[icomb] - bvec1z[icomb];
|
||||
|
||||
/* Calculate the force acted on the first atom of the angle. */
|
||||
fix = bvec2x[icomb] - cfact3 * bvec1x[icomb];
|
||||
fiy = bvec2y[icomb] - cfact3 * bvec1y[icomb];
|
||||
fiz = bvec2z[icomb] - cfact3 * bvec1z[icomb];
|
||||
|
||||
/* Finally, calculate the force acted on the middle atom of the angle.*/
|
||||
fjx = - fix - fkx; fjy = - fiy - fky; fjz = - fiz - fkz;
|
||||
|
||||
/* Consider the appropriate scaling of the forces: */
|
||||
fix *= cfact1; fiy *= cfact1; fiz *= cfact1;
|
||||
fjx *= cfact1; fjy *= cfact1; fjz *= cfact1;
|
||||
fkx *= cfact1; fky *= cfact1; fkz *= cfact1;
|
||||
|
||||
if (at1[icomb] == i1) {f1[0] += fix; f1[1] += fiy; f1[2] += fiz;}
|
||||
else if (at2[icomb] == i1) {f1[0] += fjx; f1[1] += fjy; f1[2] += fjz;}
|
||||
else if (at3[icomb] == i1) {f1[0] += fkx; f1[1] += fky; f1[2] += fkz;}
|
||||
|
||||
if (at1[icomb] == i3) {f3[0] += fix; f3[1] += fiy; f3[2] += fiz;}
|
||||
else if (at2[icomb] == i3) {f3[0] += fjx; f3[1] += fjy; f3[2] += fjz;}
|
||||
else if (at3[icomb] == i3) {f3[0] += fkx; f3[1] += fky; f3[2] += fkz;}
|
||||
|
||||
if (at1[icomb] == i4) {f4[0] += fix; f4[1] += fiy; f4[2] += fiz;}
|
||||
else if (at2[icomb] == i4) {f4[0] += fjx; f4[1] += fjy; f4[2] += fjz;}
|
||||
else if (at3[icomb] == i4) {f4[0] += fkx; f4[1] += fky; f4[2] += fkz;}
|
||||
|
||||
|
||||
/* Store the contribution to the global arrays: */
|
||||
/* Take the id of the atom from the at1[icomb] element, i1 = at1[icomb]. */
|
||||
if (NEWTON_BOND || at1[icomb] < nlocal) {
|
||||
f[at1[icomb]][0] += fix;
|
||||
f[at1[icomb]][1] += fiy;
|
||||
f[at1[icomb]][2] += fiz;
|
||||
}
|
||||
/* Take the id of the atom from the at2[icomb] element, i2 = at2[icomb]. */
|
||||
if (NEWTON_BOND || at2[icomb] < nlocal) {
|
||||
f[at2[icomb]][0] += fjx;
|
||||
f[at2[icomb]][1] += fjy;
|
||||
f[at2[icomb]][2] += fjz;
|
||||
}
|
||||
/* Take the id of the atom from the at3[icomb] element, i3 = at3[icomb]. */
|
||||
if (NEWTON_BOND || at3[icomb] < nlocal) {
|
||||
f[at3[icomb]][0] += fkx;
|
||||
f[at3[icomb]][1] += fky;
|
||||
f[at3[icomb]][2] += fkz;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(ring/omp,ImproperRingOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_RING_OMP_H
|
||||
#define LMP_IMPROPER_RING_OMP_H
|
||||
|
||||
#include "improper_ring.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperRingOMP : public ImproperRing, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperRingOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,256 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "math.h"
|
||||
#include "improper_umbrella_omp.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "neighbor.h"
|
||||
#include "domain.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "suffix.h"
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
#define TOLERANCE 0.05
|
||||
#define SMALL 0.001
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ImproperUmbrellaOMP::ImproperUmbrellaOMP(class LAMMPS *lmp)
|
||||
: ImproperUmbrella(lmp), ThrOMP(lmp,THR_IMPROPER)
|
||||
{
|
||||
suffix_flag |= Suffix::OMP;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ImproperUmbrellaOMP::compute(int eflag, int vflag)
|
||||
{
|
||||
|
||||
if (eflag || vflag) {
|
||||
ev_setup(eflag,vflag);
|
||||
} else evflag = 0;
|
||||
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
const int nthreads = comm->nthreads;
|
||||
const int inum = neighbor->nimproperlist;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(eflag,vflag)
|
||||
#endif
|
||||
{
|
||||
int ifrom, ito, tid;
|
||||
|
||||
loop_setup_thr(ifrom, ito, tid, inum, nthreads);
|
||||
ThrData *thr = fix->get_thr(tid);
|
||||
ev_setup_thr(eflag, vflag, nall, eatom, vatom, thr);
|
||||
|
||||
if (evflag) {
|
||||
if (eflag) {
|
||||
if (force->newton_bond) eval<1,1,1>(ifrom, ito, thr);
|
||||
else eval<1,1,0>(ifrom, ito, thr);
|
||||
} else {
|
||||
if (force->newton_bond) eval<1,0,1>(ifrom, ito, thr);
|
||||
else eval<1,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
} else {
|
||||
if (force->newton_bond) eval<0,0,1>(ifrom, ito, thr);
|
||||
else eval<0,0,0>(ifrom, ito, thr);
|
||||
}
|
||||
|
||||
reduce_thr(this, eflag, vflag, thr);
|
||||
} // end of omp parallel region
|
||||
}
|
||||
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void ImproperUmbrellaOMP::eval(int nfrom, int nto, ThrData * const thr)
|
||||
{
|
||||
int i1,i2,i3,i4,n,type;
|
||||
double eimproper,f1[3],f2[3],f3[3],f4[3];
|
||||
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
|
||||
double domega,c,a,s,projhfg,dhax,dhay,dhaz,dahx,dahy,dahz,cotphi;
|
||||
double ax,ay,az,ra2,rh2,ra,rh,rar,rhr,arx,ary,arz,hrx,hry,hrz;
|
||||
|
||||
eimproper = 0.0;
|
||||
|
||||
const double * const * const x = atom->x;
|
||||
double * const * const f = thr->get_f();
|
||||
const int * const * const improperlist = neighbor->improperlist;
|
||||
const int nlocal = atom->nlocal;
|
||||
|
||||
for (n = nfrom; n < nto; n++) {
|
||||
i1 = improperlist[n][0];
|
||||
i2 = improperlist[n][1];
|
||||
i3 = improperlist[n][2];
|
||||
i4 = improperlist[n][3];
|
||||
type = improperlist[n][4];
|
||||
|
||||
// 1st bond
|
||||
|
||||
vb1x = x[i2][0] - x[i1][0];
|
||||
vb1y = x[i2][1] - x[i1][1];
|
||||
vb1z = x[i2][2] - x[i1][2];
|
||||
|
||||
// 2nd bond
|
||||
|
||||
vb2x = x[i3][0] - x[i1][0];
|
||||
vb2y = x[i3][1] - x[i1][1];
|
||||
vb2z = x[i3][2] - x[i1][2];
|
||||
|
||||
// 3rd bond
|
||||
|
||||
vb3x = x[i4][0] - x[i1][0];
|
||||
vb3y = x[i4][1] - x[i1][1];
|
||||
vb3z = x[i4][2] - x[i1][2];
|
||||
|
||||
// c0 calculation
|
||||
// A = vb1 X vb2 is perpendicular to IJK plane
|
||||
|
||||
ax = vb1y*vb2z-vb1z*vb2y;
|
||||
ay = vb1z*vb2x-vb1x*vb2z;
|
||||
az = vb1x*vb2y-vb1y*vb2x;
|
||||
ra2 = ax*ax+ay*ay+az*az;
|
||||
rh2 = vb3x*vb3x+vb3y*vb3y+vb3z*vb3z;
|
||||
ra = sqrt(ra2);
|
||||
rh = sqrt(rh2);
|
||||
if (ra < SMALL) ra = SMALL;
|
||||
if (rh < SMALL) rh = SMALL;
|
||||
|
||||
rar = 1/ra;
|
||||
rhr = 1/rh;
|
||||
arx = ax*rar;
|
||||
ary = ay*rar;
|
||||
arz = az*rar;
|
||||
hrx = vb3x*rhr;
|
||||
hry = vb3y*rhr;
|
||||
hrz = vb3z*rhr;
|
||||
|
||||
c = arx*hrx+ary*hry+arz*hrz;
|
||||
|
||||
// error check
|
||||
|
||||
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
|
||||
int me = comm->me;
|
||||
|
||||
if (screen) {
|
||||
char str[128];
|
||||
sprintf(str,"Improper problem: %d/%d " BIGINT_FORMAT " %d %d %d %d",
|
||||
me,thr->get_tid(),update->ntimestep,
|
||||
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
|
||||
error->warning(FLERR,str,0);
|
||||
fprintf(screen," 1st atom: %d %g %g %g\n",
|
||||
me,x[i1][0],x[i1][1],x[i1][2]);
|
||||
fprintf(screen," 2nd atom: %d %g %g %g\n",
|
||||
me,x[i2][0],x[i2][1],x[i2][2]);
|
||||
fprintf(screen," 3rd atom: %d %g %g %g\n",
|
||||
me,x[i3][0],x[i3][1],x[i3][2]);
|
||||
fprintf(screen," 4th atom: %d %g %g %g\n",
|
||||
me,x[i4][0],x[i4][1],x[i4][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (c > 1.0) s = 1.0;
|
||||
if (c < -1.0) s = -1.0;
|
||||
|
||||
s = sqrt(1.0 - c*c);
|
||||
if (s < SMALL) s = SMALL;
|
||||
cotphi = c/s;
|
||||
|
||||
projhfg = (vb3x*vb1x+vb3y*vb1y+vb3z*vb1z) /
|
||||
sqrt(vb1x*vb1x+vb1y*vb1y+vb1z*vb1z);
|
||||
projhfg += (vb3x*vb2x+vb3y*vb2y+vb3z*vb2z) /
|
||||
sqrt(vb2x*vb2x+vb2y*vb2y+vb2z*vb2z);
|
||||
if (projhfg > 0.0) {
|
||||
s *= -1.0;
|
||||
cotphi *= -1.0;
|
||||
}
|
||||
|
||||
// force and energy
|
||||
// if w0 = 0: E = k * (1 - cos w)
|
||||
// if w0 != 0: E = 0.5 * C (cos w - cos w0)^2, C = k/(sin(w0)^2
|
||||
|
||||
if (w0[type] == 0.0) {
|
||||
if (EFLAG) eimproper = kw[type] * (1.0-s);
|
||||
a = -kw[type];
|
||||
} else {
|
||||
domega = s - cos(w0[type]);
|
||||
a = 0.5 * C[type] * domega;
|
||||
if (EFLAG) eimproper = a * domega;
|
||||
a *= 2.0;
|
||||
}
|
||||
|
||||
// dhax = diffrence between H and A in X direction, etc
|
||||
|
||||
a = a*cotphi;
|
||||
dhax = hrx-c*arx;
|
||||
dhay = hry-c*ary;
|
||||
dhaz = hrz-c*arz;
|
||||
|
||||
dahx = arx-c*hrx;
|
||||
dahy = ary-c*hry;
|
||||
dahz = arz-c*hrz;
|
||||
|
||||
f2[0] = (dhay*vb1z - dhaz*vb1y)*rar;
|
||||
f2[1] = (dhaz*vb1x - dhax*vb1z)*rar;
|
||||
f2[2] = (dhax*vb1y - dhay*vb1x)*rar;
|
||||
|
||||
f3[0] = (-dhay*vb2z + dhaz*vb2y)*rar;
|
||||
f3[1] = (-dhaz*vb2x + dhax*vb2z)*rar;
|
||||
f3[2] = (-dhax*vb2y + dhay*vb2x)*rar;
|
||||
|
||||
f4[0] = dahx*rhr;
|
||||
f4[1] = dahy*rhr;
|
||||
f4[2] = dahz*rhr;
|
||||
|
||||
f1[0] = -(f2[0] + f3[0] + f4[0]);
|
||||
f1[1] = -(f2[1] + f3[1] + f4[1]);
|
||||
f1[2] = -(f2[2] + f3[2] + f4[2]);
|
||||
|
||||
// apply force to each of 4 atoms
|
||||
|
||||
if (NEWTON_BOND || i1 < nlocal) {
|
||||
f[i1][0] += f1[0]*a;
|
||||
f[i1][1] += f1[1]*a;
|
||||
f[i1][2] += f1[2]*a;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i2 < nlocal) {
|
||||
f[i2][0] += f3[0]*a;
|
||||
f[i2][1] += f3[1]*a;
|
||||
f[i2][2] += f3[2]*a;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i3 < nlocal) {
|
||||
f[i3][0] += f2[0]*a;
|
||||
f[i3][1] += f2[1]*a;
|
||||
f[i3][2] += f2[2]*a;
|
||||
}
|
||||
|
||||
if (NEWTON_BOND || i4 < nlocal) {
|
||||
f[i4][0] += f4[0]*a;
|
||||
f[i4][1] += f4[1]*a;
|
||||
f[i4][2] += f4[2]*a;
|
||||
}
|
||||
|
||||
if (EVFLAG)
|
||||
ev_tally_thr(this,i1,i2,i3,i4,nlocal,NEWTON_BOND,eimproper,f1,f3,f4,
|
||||
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,thr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing author: Axel Kohlmeyer (Temple U)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef IMPROPER_CLASS
|
||||
|
||||
ImproperStyle(umbrella/omp,ImproperUmbrellaOMP)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_IMPROPER_UMBRELLA_OMP_H
|
||||
#define LMP_IMPROPER_UMBRELLA_OMP_H
|
||||
|
||||
#include "improper_umbrella.h"
|
||||
#include "thr_omp.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ImproperUmbrellaOMP : public ImproperUmbrella, public ThrOMP {
|
||||
|
||||
public:
|
||||
ImproperUmbrellaOMP(class LAMMPS *lmp);
|
||||
virtual void compute(int, int);
|
||||
|
||||
private:
|
||||
template <int EVFLAG, int EFLAG, int NEWTON_BOND>
|
||||
void eval(int ifrom, int ito, ThrData * const thr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,183 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
build half list from full list
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if j is ghost (also stored by proc owning j)
|
||||
works if full list is a skip list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_from_full_no_newton_omp(NeighList *list)
|
||||
{
|
||||
const int inum_full = list->listfull->inum;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(inum_full);
|
||||
|
||||
int i,j,ii,jj,n,jnum,joriginal;
|
||||
int *neighptr,*jlist;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *ilist_full = list->listfull->ilist;
|
||||
int *numneigh_full = list->listfull->numneigh;
|
||||
int **firstneigh_full = list->listfull->firstneigh;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over atoms in full list
|
||||
|
||||
for (ii = ifrom; ii < ito; ii++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
// only one thread at a time may check whether we
|
||||
// need new neighbor list pages and then add to them.
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
// loop over parent full list
|
||||
|
||||
i = ilist_full[ii];
|
||||
jlist = firstneigh_full[i];
|
||||
jnum = numneigh_full[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
joriginal = jlist[jj];
|
||||
j = joriginal & NEIGHMASK;
|
||||
if (j > i) neighptr[n++] = joriginal;
|
||||
}
|
||||
|
||||
ilist[ii] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = inum_full;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
build half list from full list
|
||||
pair stored once if i,j are both owned and i < j
|
||||
if j is ghost, only store if j coords are "above and to the right" of i
|
||||
works if full list is a skip list
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_from_full_newton_omp(NeighList *list)
|
||||
{
|
||||
const int inum_full = list->listfull->inum;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(inum_full);
|
||||
|
||||
int i,j,ii,jj,n,jnum,joriginal;
|
||||
int *neighptr,*jlist;
|
||||
double xtmp,ytmp,ztmp;
|
||||
|
||||
double **x = atom->x;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *ilist_full = list->listfull->ilist;
|
||||
int *numneigh_full = list->listfull->numneigh;
|
||||
int **firstneigh_full = list->listfull->firstneigh;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over parent full list
|
||||
|
||||
for (ii = ifrom; ii < ito; ii++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
// only one thread at a time may check whether we
|
||||
// need new neighbor list pages and then add to them.
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
i = ilist_full[ii];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over full neighbor list
|
||||
|
||||
jlist = firstneigh_full[i];
|
||||
jnum = numneigh_full[i];
|
||||
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
joriginal = jlist[jj];
|
||||
j = joriginal & NEIGHMASK;
|
||||
if (j < nlocal) {
|
||||
if (i > j) continue;
|
||||
} else {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
neighptr[n++] = joriginal;
|
||||
}
|
||||
|
||||
ilist[ii] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = inum_full;
|
||||
}
|
|
@ -0,0 +1,579 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "group.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
N^2 search for all neighbors
|
||||
every neighbor pair appears in list of both atoms i and j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::full_nsq_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,n,itype,jtype,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms, owned and ghost
|
||||
// skip i = j
|
||||
|
||||
for (j = 0; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
if (i == j) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
N^2 search for all neighbors
|
||||
include neighbors of ghost atoms, but no "special neighbors" for ghosts
|
||||
every neighbor pair appears in list of both atoms i and j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::full_nsq_ghost_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = atom->nlocal;
|
||||
const int nall = nlocal + atom->nghost;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nall);
|
||||
|
||||
int i,j,n,itype,jtype,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned & ghost atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms, owned and ghost
|
||||
// skip i = j
|
||||
// no molecular test when i = ghost atom
|
||||
|
||||
if (i < nlocal) {
|
||||
for (j = 0; j < nall; j++) {
|
||||
if (i == j) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < nall; j++) {
|
||||
if (i == j) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighghostsq[itype][jtype]) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = nall - nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction for all neighbors
|
||||
every neighbor pair appears in list of both atoms i and j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::full_bin_omp(NeighList *list)
|
||||
{
|
||||
// bin owned & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in surrounding bins in stencil including self
|
||||
// skip i = j
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (i == j) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction for all neighbors
|
||||
include neighbors of ghost atoms, but no "special neighbors" for ghosts
|
||||
every neighbor pair appears in list of both atoms i and j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::full_bin_ghost_omp(NeighList *list)
|
||||
{
|
||||
// bin owned & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = atom->nlocal;
|
||||
const int nall = nlocal + atom->nghost;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nall);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int xbin,ybin,zbin,xbin2,ybin2,zbin2;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
int **stencilxyz = list->stencilxyz;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned & ghost atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in surrounding bins in stencil including self
|
||||
// when i is a ghost atom, must check if stencil bin is out of bounds
|
||||
// skip i = j
|
||||
// no molecular test when i = ghost atom
|
||||
|
||||
if (i < nlocal) {
|
||||
ibin = coord2bin(x[i]);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (i == j) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ibin = coord2bin(x[i],xbin,ybin,zbin);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
xbin2 = xbin + stencilxyz[k][0];
|
||||
ybin2 = ybin + stencilxyz[k][1];
|
||||
zbin2 = zbin + stencilxyz[k][2];
|
||||
if (xbin2 < 0 || xbin2 >= mbinx ||
|
||||
ybin2 < 0 || ybin2 >= mbiny ||
|
||||
zbin2 < 0 || zbin2 >= mbinz) continue;
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (i == j) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighghostsq[itype][jtype]) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = nall - nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction for all neighbors
|
||||
multi-type stencil is itype dependent and is distance checked
|
||||
every neighbor pair appears in list of both atoms i and j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::full_multi_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which,ns;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr,*s;
|
||||
double *cutsq,*distsq;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *nstencil_multi = list->nstencil_multi;
|
||||
int **stencil_multi = list->stencil_multi;
|
||||
double **distsq_multi = list->distsq_multi;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in other bins in stencil, including self
|
||||
// skip if i,j neighbor cutoff is less than bin distance
|
||||
// skip i = j
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
s = stencil_multi[itype];
|
||||
distsq = distsq_multi[itype];
|
||||
cutsq = cutneighsq[itype];
|
||||
ns = nstencil_multi[itype];
|
||||
for (k = 0; k < ns; k++) {
|
||||
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
|
||||
jtype = type[j];
|
||||
if (cutsq[jtype] < distsq[k]) continue;
|
||||
if (i == j) continue;
|
||||
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = 0;
|
||||
}
|
|
@ -0,0 +1,657 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "group.h"
|
||||
#include "fix_shear_history.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
granular particles
|
||||
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
|
||||
shear history must be accounted for when a neighbor pair is added
|
||||
pair added to list if atoms i and j are both owned and i < j
|
||||
pair added if j is ghost (also stored by proc owning j)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::granular_nsq_no_newton_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
|
||||
FixShearHistory * const fix_history = list->fix_history;
|
||||
NeighList * listgranhistory = list->listgranhistory;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
|
||||
if (fix_history)
|
||||
if (nthreads > listgranhistory->maxpage)
|
||||
listgranhistory->add_pages(nthreads - listgranhistory->maxpage);
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list,listgranhistory)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,m,n,nn;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
double radi,radsum,cutsq;
|
||||
int *neighptr,*touchptr;
|
||||
double *shearptr;
|
||||
|
||||
int *npartner,**partner;
|
||||
double ***shearpartner;
|
||||
int **firsttouch;
|
||||
double **firstshear;
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *tag = atom->tag;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
if (fix_history) {
|
||||
npartner = fix_history->npartner;
|
||||
partner = fix_history->partner;
|
||||
shearpartner = fix_history->shearpartner;
|
||||
firsttouch = listgranhistory->firstneigh;
|
||||
firstshear = listgranhistory->firstdouble;
|
||||
}
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
{
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) {
|
||||
list->add_pages(nthreads);
|
||||
if (fix_history)
|
||||
listgranhistory->add_pages(nthreads);
|
||||
}
|
||||
}
|
||||
|
||||
n = nn = 0;
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
if (fix_history) {
|
||||
touchptr = &(listgranhistory->pages[npage][npnt]);
|
||||
shearptr = &(listgranhistory->dpages[npage][3*npnt]);
|
||||
}
|
||||
}
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
|
||||
// loop over remaining atoms, owned and ghost
|
||||
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) {
|
||||
neighptr[n] = j;
|
||||
|
||||
if (fix_history) {
|
||||
if (rsq < radsum*radsum) {
|
||||
for (m = 0; m < npartner[i]; m++)
|
||||
if (partner[i][m] == tag[j]) break;
|
||||
if (m < npartner[i]) {
|
||||
touchptr[n] = 1;
|
||||
shearptr[nn++] = shearpartner[i][m][0];
|
||||
shearptr[nn++] = shearpartner[i][m][1];
|
||||
shearptr[nn++] = shearpartner[i][m][2];
|
||||
} else {
|
||||
touchptr[n] = 0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
}
|
||||
} else {
|
||||
touchptr[n] = 0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
if (fix_history) {
|
||||
firsttouch[i] = touchptr;
|
||||
firstshear[i] = shearptr;
|
||||
}
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
granular particles
|
||||
N^2 / 2 search for neighbor pairs with full Newton's 3rd law
|
||||
no shear history is allowed for this option
|
||||
pair added to list if atoms i and j are both owned and i < j
|
||||
if j is ghost only me or other proc adds pair
|
||||
decision based on itag,jtag tests
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::granular_nsq_newton_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,n,itag,jtag;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
double radi,radsum,cutsq;
|
||||
int *neighptr;
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *tag = atom->tag;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itag = tag[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
|
||||
// loop over remaining atoms, owned and ghost
|
||||
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
|
||||
if (j >= nlocal) {
|
||||
jtag = tag[j];
|
||||
if (itag > jtag) {
|
||||
if ((itag+jtag) % 2 == 0) continue;
|
||||
} else if (itag < jtag) {
|
||||
if ((itag+jtag) % 2 == 1) continue;
|
||||
} else {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) neighptr[n++] = j;
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
granular particles
|
||||
binned neighbor list construction with partial Newton's 3rd law
|
||||
shear history must be accounted for when a neighbor pair is added
|
||||
each owned atom i checks own bin and surrounding bins in non-Newton stencil
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if j is ghost (also stored by proc owning j)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::granular_bin_no_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
FixShearHistory * const fix_history = list->fix_history;
|
||||
NeighList * listgranhistory = list->listgranhistory;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
|
||||
if (fix_history)
|
||||
if (nthreads > listgranhistory->maxpage)
|
||||
listgranhistory->add_pages(nthreads - listgranhistory->maxpage);
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list,listgranhistory)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,m,n,nn,ibin;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
double radi,radsum,cutsq;
|
||||
int *neighptr,*touchptr;
|
||||
double *shearptr;
|
||||
|
||||
int *npartner,**partner;
|
||||
double ***shearpartner;
|
||||
int **firsttouch;
|
||||
double **firstshear;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *tag = atom->tag;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
if (fix_history) {
|
||||
npartner = fix_history->npartner;
|
||||
partner = fix_history->partner;
|
||||
shearpartner = fix_history->shearpartner;
|
||||
firsttouch = listgranhistory->firstneigh;
|
||||
firstshear = listgranhistory->firstdouble;
|
||||
}
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
{
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) {
|
||||
list->add_pages(nthreads);
|
||||
if (fix_history)
|
||||
listgranhistory->add_pages(nthreads);
|
||||
}
|
||||
}
|
||||
|
||||
n = nn = 0;
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
if (fix_history) {
|
||||
touchptr = &(listgranhistory->pages[npage][npnt]);
|
||||
shearptr = &(listgranhistory->dpages[npage][3*npnt]);
|
||||
}
|
||||
}
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
ibin = coord2bin(x[i]);
|
||||
|
||||
// loop over all atoms in surrounding bins in stencil including self
|
||||
// only store pair if i < j
|
||||
// stores own/own pairs only once
|
||||
// stores own/ghost pairs on both procs
|
||||
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (j <= i) continue;
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) {
|
||||
neighptr[n] = j;
|
||||
|
||||
if (fix_history) {
|
||||
if (rsq < radsum*radsum) {
|
||||
for (m = 0; m < npartner[i]; m++)
|
||||
if (partner[i][m] == tag[j]) break;
|
||||
if (m < npartner[i]) {
|
||||
touchptr[n] = 1;
|
||||
shearptr[nn++] = shearpartner[i][m][0];
|
||||
shearptr[nn++] = shearpartner[i][m][1];
|
||||
shearptr[nn++] = shearpartner[i][m][2];
|
||||
} else {
|
||||
touchptr[n] = 0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
}
|
||||
} else {
|
||||
touchptr[n] = 0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
shearptr[nn++] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
if (fix_history) {
|
||||
firsttouch[i] = touchptr;
|
||||
firstshear[i] = shearptr;
|
||||
}
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
granular particles
|
||||
binned neighbor list construction with full Newton's 3rd law
|
||||
no shear history is allowed for this option
|
||||
each owned atom i checks its own bin and other bins in Newton stencil
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::granular_bin_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,ibin;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
double radi,radsum,cutsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
|
||||
// loop over rest of atoms in i's bin, ghosts are at end of linked list
|
||||
// if j is owned atom, store it, since j is beyond i in linked list
|
||||
// if j is ghost, only store if j coords are "above and to the right" of i
|
||||
|
||||
for (j = bins[i]; j >= 0; j = bins[j]) {
|
||||
if (j >= nlocal) {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) neighptr[n++] = j;
|
||||
}
|
||||
|
||||
// loop over all atoms in other bins in stencil, store every pair
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
granular particles
|
||||
binned neighbor list construction with Newton's 3rd law for triclinic
|
||||
no shear history is allowed for this option
|
||||
each owned atom i checks its own bin and other bins in triclinic stencil
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::granular_bin_newton_tri_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,ibin;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
double radi,radsum,cutsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
double **x = atom->x;
|
||||
double *radius = atom->radius;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
radi = radius[i];
|
||||
|
||||
// loop over all atoms in bins in stencil
|
||||
// pairs for atoms j "below" i are excluded
|
||||
// below = lower z or (equal z and lower y) or (equal zy and lower x)
|
||||
// (equal zyx and j <= i)
|
||||
// latter excludes self-self interaction but allows superposed atoms
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp) {
|
||||
if (x[j][0] < xtmp) continue;
|
||||
if (x[j][0] == xtmp && j <= i) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
radsum = radi + radius[j];
|
||||
cutsq = (radsum+skin) * (radsum+skin);
|
||||
|
||||
if (rsq <= cutsq) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
|
@ -0,0 +1,522 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with partial Newton's 3rd law
|
||||
each owned atom i checks own bin and other bins in stencil
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if j is ghost (also stored by proc owning j)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_bin_no_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in other bins in stencil including self
|
||||
// only store pair if i < j
|
||||
// stores own/own pairs only once
|
||||
// stores own/ghost pairs on both procs
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (j <= i) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with partial Newton's 3rd law
|
||||
include neighbors of ghost atoms, but no "special neighbors" for ghosts
|
||||
owned and ghost atoms check own bin and other bins in stencil
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if i owned and j ghost (also stored by proc owning j)
|
||||
pair stored once if i,j are both ghost and i < j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_bin_no_newton_ghost_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = atom->nlocal;
|
||||
const int nall = nlocal + atom->nghost;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nall);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
int xbin,ybin,zbin,xbin2,ybin2,zbin2;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
int **stencilxyz = list->stencilxyz;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in other bins in stencil including self
|
||||
// when i is a ghost atom, must check if stencil bin is out of bounds
|
||||
// only store pair if i < j
|
||||
// stores own/own pairs only once
|
||||
// stores own/ghost pairs with owned atom only, on both procs
|
||||
// stores ghost/ghost pairs only once
|
||||
// no molecular test when i = ghost atom
|
||||
|
||||
if (i < nlocal) {
|
||||
ibin = coord2bin(x[i]);
|
||||
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (j <= i) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ibin = coord2bin(x[i],xbin,ybin,zbin);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
xbin2 = xbin + stencilxyz[k][0];
|
||||
ybin2 = ybin + stencilxyz[k][1];
|
||||
zbin2 = zbin + stencilxyz[k][2];
|
||||
if (xbin2 < 0 || xbin2 >= mbinx ||
|
||||
ybin2 < 0 || ybin2 >= mbiny ||
|
||||
zbin2 < 0 || zbin2 >= mbinz) continue;
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (j <= i) continue;
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighghostsq[itype][jtype]) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
list->gnum = nall - atom->nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with full Newton's 3rd law
|
||||
each owned atom i checks its own bin and other bins in Newton stencil
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_bin_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over rest of atoms in i's bin, ghosts are at end of linked list
|
||||
// if j is owned atom, store it, since j is beyond i in linked list
|
||||
// if j is ghost, only store if j coords are "above and to the right" of i
|
||||
|
||||
for (j = bins[i]; j >= 0; j = bins[j]) {
|
||||
if (j >= nlocal) {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
// OLD: if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// loop over all atoms in other bins in stencil, store every pair
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
// OLD: if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with Newton's 3rd law for triclinic
|
||||
each owned atom i checks its own bin and other bins in triclinic stencil
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_bin_newton_tri_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int nstencil = list->nstencil;
|
||||
int *stencil = list->stencil;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in bins in stencil
|
||||
// pairs for atoms j "below" i are excluded
|
||||
// below = lower z or (equal z and lower y) or (equal zy and lower x)
|
||||
// (equal zyx and j <= i)
|
||||
// latter excludes self-self interaction but allows superposed atoms
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
for (k = 0; k < nstencil; k++) {
|
||||
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp) {
|
||||
if (x[j][0] < xtmp) continue;
|
||||
if (x[j][0] == xtmp && j <= i) continue;
|
||||
}
|
||||
}
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with partial Newton's 3rd law
|
||||
each owned atom i checks own bin and other bins in stencil
|
||||
multi-type stencil is itype dependent and is distance checked
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if j is ghost (also stored by proc owning j)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_multi_no_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which,ns;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr,*s;
|
||||
double *cutsq,*distsq;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *nstencil_multi = list->nstencil_multi;
|
||||
int **stencil_multi = list->stencil_multi;
|
||||
double **distsq_multi = list->distsq_multi;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in other bins in stencil including self
|
||||
// only store pair if i < j
|
||||
// skip if i,j neighbor cutoff is less than bin distance
|
||||
// stores own/own pairs only once
|
||||
// stores own/ghost pairs on both procs
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
s = stencil_multi[itype];
|
||||
distsq = distsq_multi[itype];
|
||||
cutsq = cutneighsq[itype];
|
||||
ns = nstencil_multi[itype];
|
||||
for (k = 0; k < ns; k++) {
|
||||
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
|
||||
if (j <= i) continue;
|
||||
jtype = type[j];
|
||||
if (cutsq[jtype] < distsq[k]) continue;
|
||||
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with full Newton's 3rd law
|
||||
each owned atom i checks its own bin and other bins in Newton stencil
|
||||
multi-type stencil is itype dependent and is distance checked
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_multi_newton_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which,ns;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr,*s;
|
||||
double *cutsq,*distsq;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *nstencil_multi = list->nstencil_multi;
|
||||
int **stencil_multi = list->stencil_multi;
|
||||
double **distsq_multi = list->distsq_multi;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over rest of atoms in i's bin, ghosts are at end of linked list
|
||||
// if j is owned atom, store it, since j is beyond i in linked list
|
||||
// if j is ghost, only store if j coords are "above and to the right" of i
|
||||
|
||||
for (j = bins[i]; j >= 0; j = bins[j]) {
|
||||
if (j >= nlocal) {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// loop over all atoms in other bins in stencil, store every pair
|
||||
// skip if i,j neighbor cutoff is less than bin distance
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
s = stencil_multi[itype];
|
||||
distsq = distsq_multi[itype];
|
||||
cutsq = cutneighsq[itype];
|
||||
ns = nstencil_multi[itype];
|
||||
for (k = 0; k < ns; k++) {
|
||||
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
|
||||
jtype = type[j];
|
||||
if (cutsq[jtype] < distsq[k]) continue;
|
||||
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
binned neighbor list construction with Newton's 3rd law for triclinic
|
||||
each owned atom i checks its own bin and other bins in triclinic stencil
|
||||
multi-type stencil is itype dependent and is distance checked
|
||||
every pair stored exactly once by some processor
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_multi_newton_tri_omp(NeighList *list)
|
||||
{
|
||||
// bin local & ghost atoms
|
||||
|
||||
bin_atoms();
|
||||
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,k,n,itype,jtype,ibin,which,ns;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr,*s;
|
||||
double *cutsq,*distsq;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
int *nstencil_multi = list->nstencil_multi;
|
||||
int **stencil_multi = list->stencil_multi;
|
||||
double **distsq_multi = list->distsq_multi;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over all atoms in bins, including self, in stencil
|
||||
// skip if i,j neighbor cutoff is less than bin distance
|
||||
// bins below self are excluded from stencil
|
||||
// pairs for atoms j "below" i are excluded
|
||||
// below = lower z or (equal z and lower y) or (equal zy and lower x)
|
||||
// (equal zyx and j <= i)
|
||||
// latter excludes self-self interaction but allows superposed atoms
|
||||
|
||||
ibin = coord2bin(x[i]);
|
||||
s = stencil_multi[itype];
|
||||
distsq = distsq_multi[itype];
|
||||
cutsq = cutneighsq[itype];
|
||||
ns = nstencil_multi[itype];
|
||||
for (k = 0; k < ns; k++) {
|
||||
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
|
||||
jtype = type[j];
|
||||
if (cutsq[jtype] < distsq[k]) continue;
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp) {
|
||||
if (x[j][0] < xtmp) continue;
|
||||
if (x[j][0] == xtmp && j <= i) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "neighbor.h"
|
||||
#include "neighbor_omp.h"
|
||||
#include "neigh_list.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "group.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if j is ghost (also stored by proc owning j)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_nsq_no_newton_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
const int nall = atom->nlocal + atom->nghost;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,n,itype,jtype,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over remaining atoms, owned and ghost
|
||||
// only store pair if i < j
|
||||
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
|
||||
include neighbors of ghost atoms, but no "special neighbors" for ghosts
|
||||
pair stored once if i,j are both owned and i < j
|
||||
pair stored by me if i owned and j ghost (also stored by proc owning j)
|
||||
pair stored once if i,j are both ghost and i < j
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_nsq_no_newton_ghost_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
const int nall = nlocal + atom->nghost;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nall);
|
||||
|
||||
int i,j,n,itype,jtype,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
// each thread works on its own page
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
// loop over owned & ghost atoms, storing neighbors
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over remaining atoms, owned and ghost
|
||||
// only store pair if i < j
|
||||
// stores own/own pairs only once
|
||||
// stores own/ghost pairs with owned atom only, on both procs
|
||||
// stores ghost/ghost pairs only once
|
||||
// no molecular test when i = ghost atom
|
||||
|
||||
if (i < nlocal) {
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = atom->nlocal;
|
||||
list->gnum = nall - atom->nlocal;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
N^2 / 2 search for neighbor pairs with full Newton's 3rd law
|
||||
every pair stored exactly once by some processor
|
||||
decision on ghost atoms based on itag,jtag tests
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Neighbor::half_nsq_newton_omp(NeighList *list)
|
||||
{
|
||||
const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal;
|
||||
const int bitmask = (includegroup) ? group->bitmask[includegroup] : 0;
|
||||
|
||||
NEIGH_OMP_INIT;
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel default(none) shared(list)
|
||||
#endif
|
||||
NEIGH_OMP_SETUP(nlocal);
|
||||
|
||||
int i,j,n,itype,jtype,itag,jtag,which;
|
||||
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
|
||||
int *neighptr;
|
||||
|
||||
// loop over each atom, storing neighbors
|
||||
|
||||
int **special = atom->special;
|
||||
int **nspecial = atom->nspecial;
|
||||
int *tag = atom->tag;
|
||||
|
||||
double **x = atom->x;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
int *molecule = atom->molecule;
|
||||
int nall = atom->nlocal + atom->nghost;
|
||||
int molecular = atom->molecular;
|
||||
|
||||
int *ilist = list->ilist;
|
||||
int *numneigh = list->numneigh;
|
||||
int **firstneigh = list->firstneigh;
|
||||
|
||||
int npage = tid;
|
||||
int npnt = 0;
|
||||
|
||||
for (i = ifrom; i < ito; i++) {
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp critical
|
||||
#endif
|
||||
if (pgsize - npnt < oneatom) {
|
||||
npnt = 0;
|
||||
npage += nthreads;
|
||||
if (npage >= list->maxpage) list->add_pages(nthreads);
|
||||
}
|
||||
|
||||
neighptr = &(list->pages[npage][npnt]);
|
||||
n = 0;
|
||||
|
||||
itag = tag[i];
|
||||
itype = type[i];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
|
||||
// loop over remaining atoms, owned and ghost
|
||||
// itag = jtag is possible for long cutoffs that include images of self
|
||||
|
||||
for (j = i+1; j < nall; j++) {
|
||||
if (includegroup && !(mask[j] & bitmask)) continue;
|
||||
|
||||
if (j >= nlocal) {
|
||||
jtag = tag[j];
|
||||
if (itag > jtag) {
|
||||
if ((itag+jtag) % 2 == 0) continue;
|
||||
} else if (itag < jtag) {
|
||||
if ((itag+jtag) % 2 == 1) continue;
|
||||
} else {
|
||||
if (x[j][2] < ztmp) continue;
|
||||
if (x[j][2] == ztmp) {
|
||||
if (x[j][1] < ytmp) continue;
|
||||
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jtype = type[j];
|
||||
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
|
||||
if (rsq <= cutneighsq[itype][jtype]) {
|
||||
if (molecular) {
|
||||
which = find_special(special[i],nspecial[i],tag[j]);
|
||||
if (which == 0) neighptr[n++] = j;
|
||||
else if (domain->minimum_image_check(delx,dely,delz))
|
||||
neighptr[n++] = j;
|
||||
else if (which > 0) neighptr[n++] = j ^ (which << SBBITS);
|
||||
} else neighptr[n++] = j;
|
||||
}
|
||||
}
|
||||
|
||||
ilist[i] = i;
|
||||
firstneigh[i] = neighptr;
|
||||
numneigh[i] = n;
|
||||
npnt += n;
|
||||
if (n > oneatom)
|
||||
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
|
||||
}
|
||||
NEIGH_OMP_CLOSE;
|
||||
list->inum = nlocal;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,59 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LMP_NEIGHBOR_OMP_H
|
||||
#define LMP_NEIGHBOR_OMP_H
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
// these macros hide some ugly and redundant OpenMP related stuff
|
||||
#if defined(_OPENMP)
|
||||
|
||||
// make sure we have at least one page for each thread
|
||||
#define NEIGH_OMP_INIT \
|
||||
const int nthreads = comm->nthreads; \
|
||||
if (nthreads > list->maxpage) \
|
||||
list->add_pages(nthreads - list->maxpage)
|
||||
|
||||
// get thread id and then assign each thread a fixed chunk of atoms
|
||||
#define NEIGH_OMP_SETUP(num) \
|
||||
{ \
|
||||
const int tid = omp_get_thread_num(); \
|
||||
const int idelta = 1 + num/nthreads; \
|
||||
const int ifrom = tid*idelta; \
|
||||
const int ito = ((ifrom + idelta) > num) \
|
||||
? num : (ifrom+idelta); \
|
||||
|
||||
#define NEIGH_OMP_CLOSE }
|
||||
|
||||
#else /* !defined(_OPENMP) */
|
||||
|
||||
#define NEIGH_OMP_INIT \
|
||||
const int nthreads = comm->nthreads;
|
||||
|
||||
#define NEIGH_OMP_SETUP(num) \
|
||||
const int tid = 0; \
|
||||
const int ifrom = 0; \
|
||||
const int ito = num
|
||||
|
||||
#define NEIGH_OMP_CLOSE
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue