First commit of the Elastic constant computation compute modification
This commit is contained in:
130
doc/src/compute_born.rst
Normal file
130
doc/src/compute_born.rst
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
.. index:: compute born
|
||||||
|
|
||||||
|
compute born command
|
||||||
|
====================
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
""""""
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|
||||||
|
compute ID group-ID born
|
||||||
|
|
||||||
|
* ID, group-ID are documented in :doc:`compute <compute>` command
|
||||||
|
* born = style name of this compute command
|
||||||
|
|
||||||
|
Examples
|
||||||
|
""""""""
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
compute 1 all born
|
||||||
|
|
||||||
|
Description
|
||||||
|
"""""""""""
|
||||||
|
|
||||||
|
Define a compute that calculates
|
||||||
|
:math:`\frac{\partial{}^2U}{\partial\varepsilon_{i}\partial\varepsilon_{j}}` the
|
||||||
|
second derivatives of the potential energy :math:`U` with regard to strain
|
||||||
|
tensor :math:`\varepsilon` elements. These values are related to:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
C^{B}_{i,j}=\frac{1}{V}\frac{\partial{}^2U}{\partial{}\varepsilon_{i}\partial\varepsilon_{j}}
|
||||||
|
|
||||||
|
also called the Born term of elastic contants in the stress-stress fluctuation
|
||||||
|
formalism. This quantity can be used to compute the elastic constant tensor.
|
||||||
|
Using the symmetric Voigt notation, the elastic constant tensor can be written
|
||||||
|
as a 6x6 symmetric matrix:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
C_{i,j} = \langle{}C^{B}_{i,j}\rangle
|
||||||
|
+ \frac{V}{k_{B}T}\left(\langle\sigma_{i}\sigma_{j}\rangle\right.
|
||||||
|
\left.- \langle\sigma_{i}\rangle\langle\sigma_{j}\rangle\right)
|
||||||
|
+ \frac{Nk_{B}T}{V}
|
||||||
|
\left(\delta_{i,j}+(\delta_{1,i}+\delta_{2,i}+\delta_{3,i})\right.
|
||||||
|
\left.*(\delta_{1,j}+\delta_{2,j}+\delta_{3,j})\right)
|
||||||
|
|
||||||
|
In the above expression, :math:`\sigma` stands for the virial stress
|
||||||
|
tensor, :math:`\delta` is the Kronecker delta and the usual notation apply for
|
||||||
|
the number of particle, the temperature and volume respectively :math:`N`,
|
||||||
|
:math:`T` and :math:`V`. :math `k_{B}` is the Boltzmann constant.
|
||||||
|
|
||||||
|
The Born term is a symmetric 6x6 matrix by construction and as such can be
|
||||||
|
expressed as 21 independent terms. The terms are ordered corresponding to the
|
||||||
|
following matrix element:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
\matrix{
|
||||||
|
C_{1} & C_{7} & C_{8} & C_{9} & C_{10} & C_{11} \\
|
||||||
|
C_{7} & C_{2} & C_{12} & C_{13} & C_{14} & C_{15} \\
|
||||||
|
\vdots & C_{12} & C_{3} & C_{16} & C_{17} & C_{18} \\
|
||||||
|
\vdots & C_{13} & C_{16} & C_{4} & C_{19} & C_{20} \\
|
||||||
|
\vdots & \vdots & \vdots & C_{19} & C_{5} & C_{21} \\
|
||||||
|
\vdots & \vdots & \vdots & \vdots & C_{21} & C_{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
in this matrix the indices of :math:`C_{k}` value are the corresponding index
|
||||||
|
:math:`k` in the compute output. Each term comes from the sum of every
|
||||||
|
interactions derivatives in the system as explained in :ref:`(VanWorkum)
|
||||||
|
<VanWorkum>` or :ref:`(Voyiatzis) <Voyiatzis>`.
|
||||||
|
|
||||||
|
The output can be accessed using usual Lammps routines:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
compute 1 all born
|
||||||
|
compute 2 all pressure NULL virial
|
||||||
|
variable S1 equal -c_2[1]
|
||||||
|
variable S2 equal -c_2[2]
|
||||||
|
variable S3 equal -c_2[3]
|
||||||
|
variable S4 equal -c_2[4]
|
||||||
|
variable S5 equal -c_2[5]
|
||||||
|
variable S6 equal -c_2[6]
|
||||||
|
fix 1 all ave/time 1 1 1 v_S1 v_S2 v_S3 v_S4 v_S5 v_S6 c_1[*] file born.out
|
||||||
|
|
||||||
|
In this example, the file *born.out* will contain the information needed to
|
||||||
|
compute the first and second terms of the elastic constant matrix in a post
|
||||||
|
processing procedure. The other required quantities can be accessed using any
|
||||||
|
other *LAMMPS* usual method.
|
||||||
|
|
||||||
|
NOTE: In the above :math:`C_{i,j}` computation, the term involving the virial
|
||||||
|
stress tensor :math:`\sigma` is the covariance between each elements. In a
|
||||||
|
solid the virial stress can have large variations between timesteps and average
|
||||||
|
values can be slow to converge. This term is better computed using
|
||||||
|
instantaneous values.
|
||||||
|
|
||||||
|
**Output info:**
|
||||||
|
|
||||||
|
This compute calculates a global array with the number of rows=21.
|
||||||
|
The values are ordered as explained above. These values can be used
|
||||||
|
by any command that uses a global values from a compute as input. See
|
||||||
|
the :doc:`Howto output <Howto_output>` doc page for an overview of
|
||||||
|
LAMMPS output options.
|
||||||
|
|
||||||
|
The array values calculated by this compute are all "extensive".
|
||||||
|
|
||||||
|
Restrictions
|
||||||
|
""""""""""""
|
||||||
|
|
||||||
|
The Born term can be decomposed as a product of two terms. The first one
|
||||||
|
is a general term which depends on the configuration. The second one is
|
||||||
|
specific to every interaction composing your forcefield (non-bonded,
|
||||||
|
bonds, angle...). Currently not all interaction implement the born
|
||||||
|
method giving first and second order derivatives and an error will
|
||||||
|
be raised if you try to use this compute with such interactions.
|
||||||
|
|
||||||
|
Default
|
||||||
|
"""""""
|
||||||
|
|
||||||
|
none
|
||||||
|
|
||||||
|
.. _VanWorkum:
|
||||||
|
|
||||||
|
K.Van Workum et al. J. Chem. Phys. 125 144506 (2006)
|
||||||
|
|
||||||
|
.. _Voyiatzis:
|
||||||
|
|
||||||
|
E.Voyiatzis, Computer Physics Communications 184(2013)27-33
|
||||||
@ -35,6 +35,7 @@ Angle::Angle(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
|
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
suffix_flag = Suffix::NONE;
|
suffix_flag = Suffix::NONE;
|
||||||
|
born_enable = 0;
|
||||||
|
|
||||||
maxeatom = maxvatom = maxcvatom = 0;
|
maxeatom = maxvatom = maxcvatom = 0;
|
||||||
eatom = nullptr;
|
eatom = nullptr;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class Angle : protected Pointers {
|
|||||||
int allocated;
|
int allocated;
|
||||||
int *setflag;
|
int *setflag;
|
||||||
int writedata; // 1 if writes coeffs to data file
|
int writedata; // 1 if writes coeffs to data file
|
||||||
|
int born_enable;
|
||||||
double energy; // accumulated energies
|
double energy; // accumulated energies
|
||||||
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
||||||
double *eatom, **vatom; // accumulated per-atom energy/virial
|
double *eatom, **vatom; // accumulated per-atom energy/virial
|
||||||
@ -56,6 +57,11 @@ class Angle : protected Pointers {
|
|||||||
virtual void read_restart_settings(FILE *){};
|
virtual void read_restart_settings(FILE *){};
|
||||||
virtual void write_data(FILE *) {}
|
virtual void write_data(FILE *) {}
|
||||||
virtual double single(int, int, int, int) = 0;
|
virtual double single(int, int, int, int) = 0;
|
||||||
|
virtual void born(int/*atype*/, int/*at1*/, int/*at2*/, int/*at3*/, double& du, double& du2)
|
||||||
|
{
|
||||||
|
du = 0.0;
|
||||||
|
du2 = 0.0;
|
||||||
|
}
|
||||||
virtual double memory_usage();
|
virtual double memory_usage();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -41,6 +41,7 @@ Bond::Bond(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
|
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
suffix_flag = Suffix::NONE;
|
suffix_flag = Suffix::NONE;
|
||||||
|
born_enable = 0;
|
||||||
|
|
||||||
maxeatom = maxvatom = 0;
|
maxeatom = maxvatom = 0;
|
||||||
eatom = nullptr;
|
eatom = nullptr;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ class Bond : protected Pointers {
|
|||||||
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
||||||
double *eatom, **vatom; // accumulated per-atom energy/virial
|
double *eatom, **vatom; // accumulated per-atom energy/virial
|
||||||
|
|
||||||
|
int born_enable;
|
||||||
int reinitflag; // 1 if compatible with fix adapt and alike
|
int reinitflag; // 1 if compatible with fix adapt and alike
|
||||||
|
|
||||||
// KOKKOS host/device flag and data masks
|
// KOKKOS host/device flag and data masks
|
||||||
@ -56,6 +57,12 @@ class Bond : protected Pointers {
|
|||||||
virtual void *extract(const char *, int &) { return nullptr; }
|
virtual void *extract(const char *, int &) { return nullptr; }
|
||||||
virtual void reinit();
|
virtual void reinit();
|
||||||
|
|
||||||
|
virtual void born(int/*btype*/, double/*rsq*/, int/*at1*/, int/*at2*/, double& du, double& du2)
|
||||||
|
{
|
||||||
|
du = 0.0;
|
||||||
|
du2 = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
void write_file(int, char **);
|
void write_file(int, char **);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
806
src/compute_born.cpp
Normal file
806
src/compute_born.cpp
Normal file
@ -0,0 +1,806 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
https://www.lammps.org/, 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 : Germain Clavier (UCA)
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "compute_born.h"
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "atom_vec.h"
|
||||||
|
#include "update.h"
|
||||||
|
#include "domain.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "pair.h"
|
||||||
|
#include "bond.h"
|
||||||
|
#include "angle.h"
|
||||||
|
#include "dihedral.h"
|
||||||
|
#include "improper.h"
|
||||||
|
#include "molecule.h"
|
||||||
|
#include "neigh_request.h"
|
||||||
|
#include "neigh_list.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
|
#define BIG 1000000000
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ComputeBorn::ComputeBorn(LAMMPS *lmp, int narg, char **arg) :
|
||||||
|
Compute(lmp, narg, arg)
|
||||||
|
{
|
||||||
|
MPI_Comm_rank(world,&me);
|
||||||
|
|
||||||
|
// For now the matrix can be computed as a 21 element vector
|
||||||
|
|
||||||
|
nvalues = 21;
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
|
||||||
|
// Initialize some variables
|
||||||
|
|
||||||
|
values_local = values_global = vector = NULL;
|
||||||
|
|
||||||
|
// this fix produces a global vector
|
||||||
|
|
||||||
|
memory->create(vector,nvalues,"born:vector");
|
||||||
|
memory->create(values_local,nvalues,"born:values_local");
|
||||||
|
memory->create(values_global,nvalues,"born:values_global");
|
||||||
|
size_vector = nvalues;
|
||||||
|
|
||||||
|
vector_flag = 1;
|
||||||
|
extvector = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ComputeBorn::~ComputeBorn()
|
||||||
|
{
|
||||||
|
|
||||||
|
// delete [] which;
|
||||||
|
|
||||||
|
memory->destroy(values_local);
|
||||||
|
memory->destroy(values_global);
|
||||||
|
memory->destroy(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeBorn::init()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Timestep Value
|
||||||
|
dt = update->dt;
|
||||||
|
|
||||||
|
pairflag = 0;
|
||||||
|
bondflag = 0;
|
||||||
|
angleflag = 0;
|
||||||
|
dihedflag = 0;
|
||||||
|
impflag = 0;
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
|
||||||
|
// For now this compute requires at least a pair style with pair_born method
|
||||||
|
// implemented
|
||||||
|
|
||||||
|
if (force->pair == NULL)
|
||||||
|
error->all(FLERR,"No pair style is defined for compute born");
|
||||||
|
if (force->pair->born_enable == 0) {
|
||||||
|
error->all(FLERR,"Pair style does not support compute born");
|
||||||
|
pairflag = 0;
|
||||||
|
} else {
|
||||||
|
pairflag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throws an error for now?
|
||||||
|
if (force->bond != NULL) {
|
||||||
|
if (force->bond->born_enable == 0) {
|
||||||
|
error->warning(FLERR, "Bond style does not support compute born");
|
||||||
|
bondflag = 0;
|
||||||
|
} else {
|
||||||
|
bondflag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force->angle != NULL) {
|
||||||
|
if (force->angle->born_enable == 0) {
|
||||||
|
error->warning(FLERR, "Angle style does not support compute born");
|
||||||
|
angleflag = 0;
|
||||||
|
} else {
|
||||||
|
angleflag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force->dihedral != NULL) {
|
||||||
|
if (force->dihedral->born_enable == 0) {
|
||||||
|
error->warning(FLERR, "Dihedral style does not support compute born");
|
||||||
|
dihedflag = 0;
|
||||||
|
} else {
|
||||||
|
dihedflag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force->improper != NULL) {
|
||||||
|
if (force->improper->born_enable == 0) {
|
||||||
|
error->warning(FLERR, "Improper style does not support compute born");
|
||||||
|
impflag = 0;
|
||||||
|
} else {
|
||||||
|
impflag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// need an occasional half neighbor list
|
||||||
|
int irequest = neighbor->request((void *) this);
|
||||||
|
neighbor->requests[irequest]->pair = 0;
|
||||||
|
neighbor->requests[irequest]->compute = 1;
|
||||||
|
neighbor->requests[irequest]->occasional = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeBorn::init_list(int /* id */, NeighList *ptr)
|
||||||
|
{
|
||||||
|
list = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
compute output vector
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeBorn::compute_vector()
|
||||||
|
{
|
||||||
|
invoked_array = update->ntimestep;
|
||||||
|
|
||||||
|
// zero out arrays for one sample
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nvalues; i++) values_local[i] = 0.0;
|
||||||
|
|
||||||
|
// Compute Born contribution
|
||||||
|
if (pairflag) compute_pairs();
|
||||||
|
|
||||||
|
// For now these functions are commented
|
||||||
|
if (bondflag) compute_bonds();
|
||||||
|
|
||||||
|
if (angleflag) compute_angles();
|
||||||
|
|
||||||
|
if (dihedflag) compute_dihedrals();
|
||||||
|
|
||||||
|
// Even if stated in Voyatzis-2012, improper and dihedrals
|
||||||
|
// are not exactly the same in lammps. Atoms order can depend
|
||||||
|
// on the forcefield/improper interaction used. As such,
|
||||||
|
// writing a general routine to compute improper contribution
|
||||||
|
// might be more tricky than expected.
|
||||||
|
// if (impflag) compute_impropers();
|
||||||
|
|
||||||
|
// sum Born contributions over all procs
|
||||||
|
MPI_Allreduce(values_local,values_global,nvalues,
|
||||||
|
MPI_DOUBLE,MPI_SUM,world);
|
||||||
|
|
||||||
|
int m;
|
||||||
|
for (m=0; m<nvalues; m++) {
|
||||||
|
vector[m] = values_global[m];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
compute Born contribution of local proc
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void ComputeBorn::compute_pairs()
|
||||||
|
|
||||||
|
{
|
||||||
|
int i,j,m,ii,jj,inum,jnum,itype,jtype;
|
||||||
|
double delx,dely,delz;
|
||||||
|
double rsq,factor_coul,factor_lj;
|
||||||
|
double dupair,du2pair,rinv;
|
||||||
|
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||||
|
|
||||||
|
int *type = atom->type;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
double *special_coul = force->special_coul;
|
||||||
|
double *special_lj = force->special_lj;
|
||||||
|
int newton_pair = force->newton_pair;
|
||||||
|
|
||||||
|
// invoke half neighbor list (will copy or build if necessary)
|
||||||
|
neighbor->build_one(list);
|
||||||
|
|
||||||
|
inum = list->inum;
|
||||||
|
ilist = list->ilist;
|
||||||
|
numneigh = list->numneigh;
|
||||||
|
firstneigh = list->firstneigh;
|
||||||
|
|
||||||
|
// loop over neighbors of my atoms
|
||||||
|
|
||||||
|
Pair *pair = force->pair;
|
||||||
|
double **cutsq = force->pair->cutsq;
|
||||||
|
|
||||||
|
// Declares born values
|
||||||
|
|
||||||
|
int a,b,c,d;
|
||||||
|
double xi[3];
|
||||||
|
double fi[3];
|
||||||
|
double xj[3];
|
||||||
|
double rij[3];
|
||||||
|
double pair_pref;
|
||||||
|
double r2inv;
|
||||||
|
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
while (m<nvalues) {
|
||||||
|
for (ii = 0; ii < inum; ii++) {
|
||||||
|
i = ilist[ii];
|
||||||
|
if (!(mask[i] & groupbit)) continue;
|
||||||
|
|
||||||
|
xi[0] = atom->x[i][0];
|
||||||
|
xi[1] = atom->x[i][1];
|
||||||
|
xi[2] = atom->x[i][2];
|
||||||
|
itype = type[i];
|
||||||
|
jlist = firstneigh[i];
|
||||||
|
jnum = numneigh[i];
|
||||||
|
|
||||||
|
for (jj = 0; jj < jnum; jj++) {
|
||||||
|
j = jlist[jj];
|
||||||
|
factor_lj = special_lj[sbmask(j)];
|
||||||
|
factor_coul = special_coul[sbmask(j)];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
|
||||||
|
if (!(mask[j] & groupbit)) continue;
|
||||||
|
|
||||||
|
xj[0] = atom->x[j][0];
|
||||||
|
xj[1] = atom->x[j][1];
|
||||||
|
xj[2] = atom->x[j][2];
|
||||||
|
delx = xi[0] - xj[0];
|
||||||
|
dely = xi[1] - xj[1];
|
||||||
|
delz = xi[2] - xj[2];
|
||||||
|
rij[0] = xj[0]-xi[0];
|
||||||
|
rij[1] = xj[1]-xi[1];
|
||||||
|
rij[2] = xj[2]-xi[2];
|
||||||
|
rsq = delx*delx + dely*dely + delz*delz;
|
||||||
|
r2inv = 1.0/rsq;
|
||||||
|
jtype = type[j];
|
||||||
|
|
||||||
|
if (rsq >= cutsq[itype][jtype]) continue;
|
||||||
|
|
||||||
|
if (newton_pair || j < nlocal) {
|
||||||
|
// Add contribution to Born tensor
|
||||||
|
|
||||||
|
pair->born(i,j,itype,jtype,rsq,factor_coul,factor_lj,dupair,du2pair);
|
||||||
|
pair_pref = du2pair - dupair*rinv;
|
||||||
|
|
||||||
|
// See albemunu in compute_born.h for indices order.
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
c = 0;
|
||||||
|
d = 0;
|
||||||
|
for (i = 0; i<21; i++) {
|
||||||
|
a = albemunu[i][0];
|
||||||
|
b = albemunu[i][1];
|
||||||
|
c = albemunu[i][2];
|
||||||
|
d = albemunu[i][3];
|
||||||
|
values_local[m+i] += pair_pref*rij[a]*rij[b]*rij[c]*rij[d]*r2inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m += 21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
count bonds and compute bond info on this proc
|
||||||
|
only count bond once if newton_bond is off
|
||||||
|
all atoms in interaction must be in group
|
||||||
|
all atoms in interaction must be known to proc
|
||||||
|
if bond is deleted or turned off (type <= 0)
|
||||||
|
do not count or count contribution
|
||||||
|
COMMENTED FOR NOW
|
||||||
|
---------------------------------------------------------------------- */
|
||||||
|
void ComputeBorn::compute_bonds()
|
||||||
|
{
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
int i,m,n,nb,atom1,atom2,imol,iatom,btype,ivar;
|
||||||
|
tagint tagprev;
|
||||||
|
double dx,dy,dz,rsq;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
double **v = atom->v;
|
||||||
|
int *type = atom->type;
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int *num_bond = atom->num_bond;
|
||||||
|
tagint **bond_atom = atom->bond_atom;
|
||||||
|
int **bond_type = atom->bond_type;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
|
||||||
|
int *molindex = atom->molindex;
|
||||||
|
int *molatom = atom->molatom;
|
||||||
|
Molecule **onemols = atom->avec->onemols;
|
||||||
|
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int newton_bond = force->newton_bond;
|
||||||
|
int molecular = atom->molecular;
|
||||||
|
|
||||||
|
Bond *bond = force->bond;
|
||||||
|
|
||||||
|
int a,b,c,d;
|
||||||
|
double rij[3];
|
||||||
|
double rinv, r2inv;
|
||||||
|
double pair_pref, dupair, du2pair;
|
||||||
|
|
||||||
|
// loop over all atoms and their bonds
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
while (m<nvalues) {
|
||||||
|
|
||||||
|
for (atom1 = 0; atom1 < nlocal; atom1++) {
|
||||||
|
if (!(mask[atom1] & groupbit)) continue;
|
||||||
|
|
||||||
|
if (molecular == 1) nb = num_bond[atom1];
|
||||||
|
else {
|
||||||
|
if (molindex[atom1] < 0) continue;
|
||||||
|
imol = molindex[atom1];
|
||||||
|
iatom = molatom[atom1];
|
||||||
|
nb = onemols[imol]->num_bond[iatom];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nb; i++) {
|
||||||
|
if (molecular == 1) {
|
||||||
|
btype = bond_type[atom1][i];
|
||||||
|
atom2 = atom->map(bond_atom[atom1][i]);
|
||||||
|
} else {
|
||||||
|
tagprev = tag[atom1] - iatom - 1;
|
||||||
|
btype = onemols[imol]->bond_type[iatom][i];
|
||||||
|
atom2 = atom->map(onemols[imol]->bond_atom[iatom][i]+tagprev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atom2 < 0 || !(mask[atom2] & groupbit)) continue;
|
||||||
|
if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
|
||||||
|
if (btype <= 0) continue;
|
||||||
|
|
||||||
|
dx = x[atom2][0] - x[atom1][0];
|
||||||
|
dy = x[atom2][1] - x[atom1][1];
|
||||||
|
dz = x[atom2][2] - x[atom1][2];
|
||||||
|
domain->minimum_image(dx,dy,dz);
|
||||||
|
rsq = dx*dx + dy*dy + dz*dz;
|
||||||
|
rij[0] = dx;
|
||||||
|
rij[1] = dy;
|
||||||
|
rij[2] = dz;
|
||||||
|
r2inv = 1.0/rsq;
|
||||||
|
rinv = sqrt(r2inv);
|
||||||
|
|
||||||
|
pair_pref = 0.0;
|
||||||
|
dupair = 0.0;
|
||||||
|
du2pair = 0.0;
|
||||||
|
bond->born(btype,rsq,atom1,atom2,dupair,du2pair);
|
||||||
|
pair_pref = du2pair - dupair*rinv;
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
c = 0;
|
||||||
|
d = 0;
|
||||||
|
for (i = 0; i<21; i++) {
|
||||||
|
a = albemunu[i][0];
|
||||||
|
b = albemunu[i][1];
|
||||||
|
c = albemunu[i][2];
|
||||||
|
d = albemunu[i][3];
|
||||||
|
values_local[m+i] += pair_pref*rij[a]*rij[b]*rij[c]*rij[d]*r2inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m += 21;
|
||||||
|
}
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
count angles and compute angle info on this proc
|
||||||
|
only count if 2nd atom is the one storing the angle
|
||||||
|
all atoms in interaction must be in group
|
||||||
|
all atoms in interaction must be known to proc
|
||||||
|
if bond is deleted or turned off (type <= 0)
|
||||||
|
do not count or count contribution
|
||||||
|
COMMENTED FOR NOW
|
||||||
|
---------------------------------------------------------------------- */
|
||||||
|
void ComputeBorn::compute_angles()
|
||||||
|
{
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
int i,m,n,na,atom1,atom2,atom3,imol,iatom,atype,ivar;
|
||||||
|
tagint tagprev;
|
||||||
|
double delx1,dely1,delz1,delx2,dely2,delz2;
|
||||||
|
double rsq1,rsq2,r1,r2,cost;
|
||||||
|
double r1r2, r1r2inv;
|
||||||
|
double rsq1inv,rsq2inv,r1inv,r2inv,cinv;
|
||||||
|
double *ptr;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int *num_angle = atom->num_angle;
|
||||||
|
tagint **angle_atom1 = atom->angle_atom1;
|
||||||
|
tagint **angle_atom2 = atom->angle_atom2;
|
||||||
|
tagint **angle_atom3 = atom->angle_atom3;
|
||||||
|
int **angle_type = atom->angle_type;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
|
||||||
|
int *molindex = atom->molindex;
|
||||||
|
int *molatom = atom->molatom;
|
||||||
|
Molecule **onemols = atom->avec->onemols;
|
||||||
|
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int molecular = atom->molecular;
|
||||||
|
|
||||||
|
// loop over all atoms and their angles
|
||||||
|
|
||||||
|
Angle *angle = force->angle;
|
||||||
|
|
||||||
|
int a,b,c,d,e,f;
|
||||||
|
double duang, du2ang;
|
||||||
|
double del1[3], del2[3];
|
||||||
|
double dcos[6];
|
||||||
|
double d2cos[21];
|
||||||
|
double d2lncos[21];
|
||||||
|
|
||||||
|
// Initializing array for intermediate cos derivatives
|
||||||
|
// w regard to strain
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
dcos[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 21; i++) {
|
||||||
|
d2cos[i] = 0;
|
||||||
|
d2lncos[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
while (m < nvalues) {
|
||||||
|
for (atom2 = 0; atom2 < nlocal; atom2++) {
|
||||||
|
if (!(mask[atom2] & groupbit)) continue;
|
||||||
|
|
||||||
|
if (molecular == 1) na = num_angle[atom2];
|
||||||
|
else {
|
||||||
|
if (molindex[atom2] < 0) continue;
|
||||||
|
imol = molindex[atom2];
|
||||||
|
iatom = molatom[atom2];
|
||||||
|
na = onemols[imol]->num_angle[iatom];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < na; i++) {
|
||||||
|
if (molecular == 1) {
|
||||||
|
if (tag[atom2] != angle_atom2[atom2][i]) continue;
|
||||||
|
atype = angle_type[atom2][i];
|
||||||
|
atom1 = atom->map(angle_atom1[atom2][i]);
|
||||||
|
atom3 = atom->map(angle_atom3[atom2][i]);
|
||||||
|
} else {
|
||||||
|
if (tag[atom2] != onemols[imol]->angle_atom2[atom2][i]) continue;
|
||||||
|
atype = onemols[imol]->angle_type[atom2][i];
|
||||||
|
tagprev = tag[atom2] - iatom - 1;
|
||||||
|
atom1 = atom->map(onemols[imol]->angle_atom1[atom2][i]+tagprev);
|
||||||
|
atom3 = atom->map(onemols[imol]->angle_atom3[atom2][i]+tagprev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
|
||||||
|
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
|
||||||
|
if (atype <= 0) continue;
|
||||||
|
|
||||||
|
delx1 = x[atom1][0] - x[atom2][0];
|
||||||
|
dely1 = x[atom1][1] - x[atom2][1];
|
||||||
|
delz1 = x[atom1][2] - x[atom2][2];
|
||||||
|
domain->minimum_image(delx1,dely1,delz1);
|
||||||
|
del1[0] = delx1;
|
||||||
|
del1[1] = dely1;
|
||||||
|
del1[2] = delz1;
|
||||||
|
|
||||||
|
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
|
||||||
|
rsq1inv = 1.0/rsq1;
|
||||||
|
r1 = sqrt(rsq1);
|
||||||
|
r1inv = 1.0/r1;
|
||||||
|
|
||||||
|
delx2 = x[atom3][0] - x[atom2][0];
|
||||||
|
dely2 = x[atom3][1] - x[atom2][1];
|
||||||
|
delz2 = x[atom3][2] - x[atom2][2];
|
||||||
|
domain->minimum_image(delx2,dely2,delz2);
|
||||||
|
del2[0] = delx2;
|
||||||
|
del2[1] = dely2;
|
||||||
|
del2[2] = delz2;
|
||||||
|
|
||||||
|
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
|
||||||
|
rsq2inv = 1.0/rsq2;
|
||||||
|
r2 = sqrt(rsq2);
|
||||||
|
r2inv = 1.0/r2;
|
||||||
|
|
||||||
|
r1r2 = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||||
|
r1r2inv = 1/r1r2;
|
||||||
|
// cost = cosine of angle
|
||||||
|
|
||||||
|
cost = delx1*delx2 + dely1*dely2 + delz1*delz2;
|
||||||
|
cost /= r1*r2;
|
||||||
|
if (cost > 1.0) cost = 1.0;
|
||||||
|
if (cost < -1.0) cost = -1.0;
|
||||||
|
cinv = 1.0/cost;
|
||||||
|
|
||||||
|
// The method must return derivative with regards
|
||||||
|
// to cos(theta)!
|
||||||
|
// Use the chain rule if needed:
|
||||||
|
// dU(t)/de = dt/dcos(t)*dU(t)/dt*dcos(t)/de
|
||||||
|
// with dt/dcos(t) = -1/sin(t)
|
||||||
|
angle->born(atype,atom1,atom2,atom3,duang,du2ang);
|
||||||
|
|
||||||
|
// Voigt notation
|
||||||
|
// 1 = 11, 2 = 22, 3 = 33
|
||||||
|
// 4 = 23, 5 = 13, 6 = 12
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
c = 0;
|
||||||
|
d = 0;
|
||||||
|
for (i = 0; i<6; i++) {
|
||||||
|
a = albe[i][0];
|
||||||
|
b = albe[i][1];
|
||||||
|
dcos[i] = cost*(del1[a]*del2[b]+del1[b]*del2[a]*r1r2inv -
|
||||||
|
del1[a]*del1[b]*rsq1inv - del2[a]*del2[b]*rsq2inv);
|
||||||
|
}
|
||||||
|
for (i = 0; i<21; i++) {
|
||||||
|
a = albemunu[i][0];
|
||||||
|
b = albemunu[i][1];
|
||||||
|
c = albemunu[i][2];
|
||||||
|
d = albemunu[i][3];
|
||||||
|
e = albe[i][0];
|
||||||
|
f = albe[i][1];
|
||||||
|
d2lncos[i] = 2*(del1[a]*del1[b]*del1[c]*del1[d]*rsq1inv*rsq1inv +
|
||||||
|
del2[a]*del2[b]*del2[c]*del2[d]*rsq2inv*rsq2inv) -
|
||||||
|
(del1[a]*del2[b]+del1[b]*del2[a]) *
|
||||||
|
(del1[c]*del2[d]+del1[d]*del2[c]) *
|
||||||
|
r1r2inv*r1r2inv;
|
||||||
|
d2cos[i] = cost*d2lncos[i] + dcos[e]*dcos[f]*cinv;
|
||||||
|
values_local[m+i] += duang*d2cos[i] + du2ang*dcos[e]*dcos[f];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m+=21;
|
||||||
|
}
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
count dihedrals on this proc
|
||||||
|
only count if 2nd atom is the one storing the dihedral
|
||||||
|
all atoms in interaction must be in group
|
||||||
|
all atoms in interaction must be known to proc
|
||||||
|
if flag is set, compute requested info about dihedral
|
||||||
|
COMMENTED FOR NOW
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void ComputeBorn::compute_dihedrals()
|
||||||
|
{
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
int i,m,n,nd,atom1,atom2,atom3,atom4,imol,iatom,dtype,ivar;
|
||||||
|
tagint tagprev;
|
||||||
|
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
|
||||||
|
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,ra2inv,rb2inv,rabinv;
|
||||||
|
double si,co,phi;
|
||||||
|
double *ptr;
|
||||||
|
|
||||||
|
double **x = atom->x;
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int *num_dihedral = atom->num_dihedral;
|
||||||
|
tagint **dihedral_atom1 = atom->dihedral_atom1;
|
||||||
|
tagint **dihedral_atom2 = atom->dihedral_atom2;
|
||||||
|
tagint **dihedral_atom3 = atom->dihedral_atom3;
|
||||||
|
tagint **dihedral_atom4 = atom->dihedral_atom4;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
|
||||||
|
int *molindex = atom->molindex;
|
||||||
|
int *molatom = atom->molatom;
|
||||||
|
Molecule **onemols = atom->avec->onemols;
|
||||||
|
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int molecular = atom->molecular;
|
||||||
|
|
||||||
|
// loop over all atoms and their dihedrals
|
||||||
|
|
||||||
|
Dihedral *dihedral = force->dihedral;
|
||||||
|
|
||||||
|
double dudih,du2dih;
|
||||||
|
int a,b,c,d,e,f;
|
||||||
|
double b1sq;
|
||||||
|
double b2sq;
|
||||||
|
double b3sq;
|
||||||
|
double b1b2;
|
||||||
|
double b1b3;
|
||||||
|
double b2b3;
|
||||||
|
double b1[3];
|
||||||
|
double b2[3];
|
||||||
|
double b3[3];
|
||||||
|
|
||||||
|
// Actually derivatives of the square of the
|
||||||
|
// vectors dot product.
|
||||||
|
double dmn[6];
|
||||||
|
double dmm[6];
|
||||||
|
double dnn[6];
|
||||||
|
double d2mn[21];
|
||||||
|
double d2mm[21];
|
||||||
|
double d2nn[21];
|
||||||
|
|
||||||
|
double dcos[6];
|
||||||
|
double d2cos[21];
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
dmn[i] =0;
|
||||||
|
dmm[i] = 0;
|
||||||
|
dnn[i] = 0;
|
||||||
|
dcos[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 21; i++) {
|
||||||
|
d2mn[i] = 0;
|
||||||
|
d2mm[i] = 0;
|
||||||
|
d2nn[i] = 0;
|
||||||
|
d2cos[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
while (m < nvalues) {
|
||||||
|
for (atom2 = 0; atom2 < nlocal; atom2++) {
|
||||||
|
if (!(mask[atom2] & groupbit)) continue;
|
||||||
|
|
||||||
|
if (molecular == 1) nd = num_dihedral[atom2];
|
||||||
|
else {
|
||||||
|
if (molindex[atom2] < 0) continue;
|
||||||
|
imol = molindex[atom2];
|
||||||
|
iatom = molatom[atom2];
|
||||||
|
nd = onemols[imol]->num_dihedral[iatom];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nd; i++) {
|
||||||
|
if (molecular == 1) {
|
||||||
|
if (tag[atom2] != dihedral_atom2[atom2][i]) continue;
|
||||||
|
atom1 = atom->map(dihedral_atom1[atom2][i]);
|
||||||
|
atom3 = atom->map(dihedral_atom3[atom2][i]);
|
||||||
|
atom4 = atom->map(dihedral_atom4[atom2][i]);
|
||||||
|
} else {
|
||||||
|
if (tag[atom2] != onemols[imol]->dihedral_atom2[atom2][i]) continue;
|
||||||
|
tagprev = tag[atom2] - iatom - 1;
|
||||||
|
atom1 = atom->map(onemols[imol]->dihedral_atom1[atom2][i]+tagprev);
|
||||||
|
atom3 = atom->map(onemols[imol]->dihedral_atom3[atom2][i]+tagprev);
|
||||||
|
atom4 = atom->map(onemols[imol]->dihedral_atom4[atom2][i]+tagprev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
|
||||||
|
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
|
||||||
|
if (atom4 < 0 || !(mask[atom4] & groupbit)) continue;
|
||||||
|
|
||||||
|
// phi calculation from dihedral style harmonic
|
||||||
|
|
||||||
|
// The method must return derivative with regards
|
||||||
|
// to cos(phi)!
|
||||||
|
// Use the chain rule if needed:
|
||||||
|
// dU(t)/de = dt/dcos(t)*dU(t)/dt*dcos(t)/de
|
||||||
|
// with dt/dcos(t) = -1/sin(t)
|
||||||
|
|
||||||
|
dihedral->born(nd,atom1,atom2,atom3,atom4,dudih,du2dih);
|
||||||
|
|
||||||
|
vb1x = x[atom1][0] - x[atom2][0];
|
||||||
|
vb1y = x[atom1][1] - x[atom2][1];
|
||||||
|
vb1z = x[atom1][2] - x[atom2][2];
|
||||||
|
domain->minimum_image(vb1x,vb1y,vb1z);
|
||||||
|
b1[0] = vb1x;
|
||||||
|
b1[1] = vb1y;
|
||||||
|
b1[2] = vb1z;
|
||||||
|
b1sq = b1[0]*b1[0]+b1[1]*b1[1]+b1[2]*b1[2];
|
||||||
|
|
||||||
|
vb2x = x[atom3][0] - x[atom2][0];
|
||||||
|
vb2y = x[atom3][1] - x[atom2][1];
|
||||||
|
vb2z = x[atom3][2] - x[atom2][2];
|
||||||
|
domain->minimum_image(vb2x,vb2y,vb2z);
|
||||||
|
b2[0] = vb2x;
|
||||||
|
b2[1] = vb2y;
|
||||||
|
b2[2] = vb2z;
|
||||||
|
b2sq = b2[0]*b2[0]+b2[1]*b2[1]+b2[2]*b2[2];
|
||||||
|
|
||||||
|
vb2xm = -vb2x;
|
||||||
|
vb2ym = -vb2y;
|
||||||
|
vb2zm = -vb2z;
|
||||||
|
domain->minimum_image(vb2xm,vb2ym,vb2zm);
|
||||||
|
|
||||||
|
vb3x = x[atom4][0] - x[atom3][0];
|
||||||
|
vb3y = x[atom4][1] - x[atom3][1];
|
||||||
|
vb3z = x[atom4][2] - x[atom3][2];
|
||||||
|
domain->minimum_image(vb3x,vb3y,vb3z);
|
||||||
|
b3[0] = vb3x;
|
||||||
|
b3[1] = vb3y;
|
||||||
|
b3[2] = vb3z;
|
||||||
|
b3sq = b3[0]*b3[0]+b3[1]*b3[1]+b3[2]*b3[2];
|
||||||
|
|
||||||
|
b1b2 = b1[0]*b2[0]+b1[1]*b2[1]+b1[2]*b2[2];
|
||||||
|
b1b3 = b1[0]*b3[0]+b1[1]*b3[1]+b1[2]*b3[2];
|
||||||
|
b2b3 = b2[0]*b3[0]+b2[1]*b3[1]+b2[2]*b3[2];
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
ra2inv = rb2inv = 0.0;
|
||||||
|
if (rasq > 0) ra2inv = 1.0/rasq;
|
||||||
|
if (rbsq > 0) rb2inv = 1.0/rbsq;
|
||||||
|
rabinv = sqrt(ra2inv*rb2inv);
|
||||||
|
|
||||||
|
co = (ax*bx + ay*by + az*bz)*rabinv;
|
||||||
|
si = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
|
||||||
|
|
||||||
|
if (co > 1.0) co = 1.0;
|
||||||
|
if (co < -1.0) co = -1.0;
|
||||||
|
phi = atan2(si,co);
|
||||||
|
|
||||||
|
// above a and b are m and n vectors
|
||||||
|
// here they are integers indices
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
c = 0;
|
||||||
|
d = 0;
|
||||||
|
e = 0;
|
||||||
|
f = 0;
|
||||||
|
for (i = 0; i<6; i++) {
|
||||||
|
a = albe[i][0];
|
||||||
|
b = albe[i][1];
|
||||||
|
dmm[i] = 2*(b2sq*b1[a]*b1[b]+b1sq*b2[a]*b2[b] - b1b2*(b1[a]*b2[b]+b1[b]*b2[a]));
|
||||||
|
dnn[i] = 2*(b3sq*b2[a]*b2[b]+b2sq*b3[a]*b3[b] - b2b3*(b2[a]*b3[b]+b2[b]*b3[a]));
|
||||||
|
dmn[i] = b1b2*(b2[a]*b3[b]+b2[b]*b3[a]) + b2b3*(b1[a]*b2[b]+b1[b]*b2[a])
|
||||||
|
- 2*(b1b3*b2[a]*b2[b]) - b2sq*(b1[a]*b3[b]+b1[b]*b3[a]);
|
||||||
|
dcos[i] = co*(rabinv*rabinv*dmn[i] - ra2inv*dmm[i] - rb2inv*dnn[i])/2.;
|
||||||
|
}
|
||||||
|
for (i = 0; i<21; i++) {
|
||||||
|
a = albemunu[i][0];
|
||||||
|
b = albemunu[i][1];
|
||||||
|
c = albemunu[i][2];
|
||||||
|
d = albemunu[i][3];
|
||||||
|
e = albe[i][0];
|
||||||
|
f = albe[i][1];
|
||||||
|
d2mm[i] = 4*(b1[a]*b1[b]*b2[c]*b2[d] + b1[c]*b1[d]*b2[a]*b2[b])
|
||||||
|
- 8*(b1[a]*b2[b]+b1[b]*b2[a])*(b1[c]*b2[d]+b1[d]*b2[c]);
|
||||||
|
d2nn[i] = 4*(b2[a]*b2[b]*b3[c]*b3[d] + b2[c]*b2[d]*b3[a]*b3[b])
|
||||||
|
- 8*(b2[a]*b3[b]+b2[b]*b3[a])*(b2[c]*b3[d]+b2[d]*b3[c]);
|
||||||
|
d2mn[i] = (b1[a]*b2[b]+b1[b]*b2[a])*(b2[c]*b3[d]+b2[d]*b3[c])
|
||||||
|
+ (b2[a]*b3[b]+b2[b]*b3[a])*(b1[c]*b2[d]+b1[d]*b2[d])
|
||||||
|
- (b1[a]*b3[b]+b1[b]*b3[a])*(b2[c]*b2[d]+b2[c]*b2[d])
|
||||||
|
- (b1[c]*b3[d]+b1[d]*b3[c])*(b2[a]*b2[b]+b2[a]*b2[b]);
|
||||||
|
d2cos[i] = co/2.*(
|
||||||
|
rabinv*rabinv*d2mn[i]
|
||||||
|
- rabinv*rabinv*rabinv*rabinv*dmn[e]*dmn[f]
|
||||||
|
+ ra2inv*ra2inv*dmm[e]*dmm[f]
|
||||||
|
- ra2inv*d2mm[i]
|
||||||
|
+ rb2inv*rb2inv*dnn[e]*dnn[f]
|
||||||
|
- rb2inv*d2nn[i] );
|
||||||
|
values_local[m+i] += dudih*d2cos[i] + du2dih*dcos[e]*dcos[f];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m+=21;
|
||||||
|
}
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
}
|
||||||
125
src/compute_born.h
Normal file
125
src/compute_born.h
Normal file
@ -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 Authors : Germain Clavier (UCA)
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef COMPUTE_CLASS
|
||||||
|
|
||||||
|
ComputeStyle(born,ComputeBorn)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_COMPUTE_BORN_H
|
||||||
|
#define LMP_COMPUTE_BORN_H
|
||||||
|
|
||||||
|
#include "compute.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class ComputeBorn : public Compute {
|
||||||
|
public:
|
||||||
|
ComputeBorn(class LAMMPS *, int, char **);
|
||||||
|
virtual ~ComputeBorn();
|
||||||
|
void init();
|
||||||
|
void init_list(int, class NeighList *);
|
||||||
|
void compute_vector();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void compute_pairs();
|
||||||
|
void compute_bonds();
|
||||||
|
void compute_angles();
|
||||||
|
void compute_dihedrals();
|
||||||
|
void compute_impropers();
|
||||||
|
|
||||||
|
int me,nvalues;
|
||||||
|
int *which;
|
||||||
|
|
||||||
|
int pairflag, bondflag, angleflag;
|
||||||
|
int dihedflag, impflag;
|
||||||
|
|
||||||
|
int const albe[21][2] = {
|
||||||
|
{0,0}, // C11
|
||||||
|
{1,1}, // C22
|
||||||
|
{2,2}, // C33
|
||||||
|
{1,2}, // C44
|
||||||
|
{0,2}, // C55
|
||||||
|
{0,1}, // C66
|
||||||
|
{0,1}, // C12
|
||||||
|
{0,2}, // C13
|
||||||
|
{0,3}, // C14
|
||||||
|
{0,4}, // C15
|
||||||
|
{0,5}, // C16
|
||||||
|
{1,2}, // C23
|
||||||
|
{1,3}, // C24
|
||||||
|
{1,4}, // C25
|
||||||
|
{1,5}, // C26
|
||||||
|
{2,3}, // C34
|
||||||
|
{2,4}, // C35
|
||||||
|
{2,5}, // C36
|
||||||
|
{3,4}, // C45
|
||||||
|
{3,5}, // C46
|
||||||
|
{4,5} // C56
|
||||||
|
};
|
||||||
|
|
||||||
|
int const albemunu[21][4] = {
|
||||||
|
{0,0,0,0}, // C11
|
||||||
|
{1,1,1,1}, // C22
|
||||||
|
{2,2,2,2}, // C33
|
||||||
|
{1,2,1,2}, // C44
|
||||||
|
{0,2,0,2}, // C55
|
||||||
|
{0,1,0,1}, // C66
|
||||||
|
{0,0,1,1}, // C12
|
||||||
|
{0,0,2,2}, // C13
|
||||||
|
{0,0,1,2}, // C14
|
||||||
|
{0,0,0,2}, // C15
|
||||||
|
{0,0,0,1}, // C16
|
||||||
|
{1,1,2,2}, // C23
|
||||||
|
{1,1,1,2}, // C24
|
||||||
|
{1,1,0,2}, // C25
|
||||||
|
{1,1,0,1}, // C26
|
||||||
|
{2,2,1,2}, // C34
|
||||||
|
{2,2,0,2}, // C35
|
||||||
|
{2,2,0,1}, // C36
|
||||||
|
{1,2,0,2}, // C45
|
||||||
|
{1,2,0,1}, // C46
|
||||||
|
{0,1,0,2} // C56
|
||||||
|
};
|
||||||
|
|
||||||
|
double *values_local,*values_global;
|
||||||
|
double pos,pos1,dt,nktv2p,ftm2v;
|
||||||
|
class NeighList *list;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ERROR/WARNING messages:
|
||||||
|
|
||||||
|
E: Illegal ... command
|
||||||
|
|
||||||
|
Self-explanatory. Check the input script syntax and compare to the
|
||||||
|
documentation for the command. You can use -echo screen as a
|
||||||
|
command-line option when running LAMMPS to see the offending line.
|
||||||
|
|
||||||
|
E: ... style does not support compute born
|
||||||
|
|
||||||
|
Some component of the force field (pair, bond, angle...) does not provide
|
||||||
|
a function to return the Born term contribution.
|
||||||
|
*/
|
||||||
|
|
||||||
@ -36,6 +36,7 @@ Dihedral::Dihedral(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
|
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
suffix_flag = Suffix::NONE;
|
suffix_flag = Suffix::NONE;
|
||||||
|
born_enable = 0;
|
||||||
|
|
||||||
maxeatom = maxvatom = maxcvatom = 0;
|
maxeatom = maxvatom = maxcvatom = 0;
|
||||||
eatom = nullptr;
|
eatom = nullptr;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class Dihedral : protected Pointers {
|
|||||||
int allocated;
|
int allocated;
|
||||||
int *setflag;
|
int *setflag;
|
||||||
int writedata; // 1 if writes coeffs to data file
|
int writedata; // 1 if writes coeffs to data file
|
||||||
|
int born_enable;
|
||||||
double energy; // accumulated energy
|
double energy; // accumulated energy
|
||||||
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
||||||
double *eatom, **vatom; // accumulated per-atom energy/virial
|
double *eatom, **vatom; // accumulated per-atom energy/virial
|
||||||
@ -55,6 +56,11 @@ class Dihedral : protected Pointers {
|
|||||||
virtual void read_restart_settings(FILE *){};
|
virtual void read_restart_settings(FILE *){};
|
||||||
virtual void write_data(FILE *) {}
|
virtual void write_data(FILE *) {}
|
||||||
virtual double memory_usage();
|
virtual double memory_usage();
|
||||||
|
virtual void born(int/*dtype*/, int/*at1*/, int/*at2*/, int/*at3*/, int /*at4*/, double& du, double& du2)
|
||||||
|
{
|
||||||
|
du = 0.0;
|
||||||
|
du2 = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int suffix_flag; // suffix compatibility flag
|
int suffix_flag; // suffix compatibility flag
|
||||||
|
|||||||
@ -34,6 +34,7 @@ Improper::Improper(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
|
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
suffix_flag = Suffix::NONE;
|
suffix_flag = Suffix::NONE;
|
||||||
|
born_enable = 0;
|
||||||
|
|
||||||
maxeatom = maxvatom = maxcvatom = 0;
|
maxeatom = maxvatom = maxcvatom = 0;
|
||||||
eatom = nullptr;
|
eatom = nullptr;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class Improper : protected Pointers {
|
|||||||
int allocated;
|
int allocated;
|
||||||
int *setflag;
|
int *setflag;
|
||||||
int writedata; // 1 if writes coeffs to data file
|
int writedata; // 1 if writes coeffs to data file
|
||||||
|
int born_enable;
|
||||||
double energy; // accumulated energies
|
double energy; // accumulated energies
|
||||||
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
double virial[6]; // accumulated virial: xx,yy,zz,xy,xz,yz
|
||||||
double *eatom, **vatom; // accumulated per-atom energy/virial
|
double *eatom, **vatom; // accumulated per-atom energy/virial
|
||||||
@ -55,6 +56,11 @@ class Improper : protected Pointers {
|
|||||||
virtual void read_restart_settings(FILE *){};
|
virtual void read_restart_settings(FILE *){};
|
||||||
virtual void write_data(FILE *) {}
|
virtual void write_data(FILE *) {}
|
||||||
virtual double memory_usage();
|
virtual double memory_usage();
|
||||||
|
virtual void born(int/*dtype*/, int/*at1*/, int/*at2*/, int/*at3*/, int /*at4*/, double& du, double& du2)
|
||||||
|
{
|
||||||
|
du = 0.0;
|
||||||
|
du2 = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int suffix_flag; // suffix compatibility flag
|
int suffix_flag; // suffix compatibility flag
|
||||||
|
|||||||
@ -58,6 +58,7 @@ Pair::Pair(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
comm_forward = comm_reverse = comm_reverse_off = 0;
|
comm_forward = comm_reverse = comm_reverse_off = 0;
|
||||||
|
|
||||||
single_enable = 1;
|
single_enable = 1;
|
||||||
|
born_enable = 0;
|
||||||
single_hessian_enable = 0;
|
single_hessian_enable = 0;
|
||||||
restartinfo = 1;
|
restartinfo = 1;
|
||||||
respa_enable = 0;
|
respa_enable = 0;
|
||||||
|
|||||||
@ -51,6 +51,7 @@ class Pair : protected Pointers {
|
|||||||
int comm_reverse_off; // size of reverse comm even if newton off
|
int comm_reverse_off; // size of reverse comm even if newton off
|
||||||
|
|
||||||
int single_enable; // 1 if single() routine exists
|
int single_enable; // 1 if single() routine exists
|
||||||
|
int born_enable; // 1 if born() routine exists
|
||||||
int single_hessian_enable; // 1 if single_hessian() routine exists
|
int single_hessian_enable; // 1 if single_hessian() routine exists
|
||||||
int restartinfo; // 1 if pair style writes restart info
|
int restartinfo; // 1 if pair style writes restart info
|
||||||
int respa_enable; // 1 if inner/middle/outer rRESPA routines
|
int respa_enable; // 1 if inner/middle/outer rRESPA routines
|
||||||
@ -158,6 +159,13 @@ class Pair : protected Pointers {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void born(int /*i*/, int /*j*/, int /*itype*/, int /*jtype*/, double /*rsq*/,
|
||||||
|
double /*factor_coul*/, double /*factor_lj*/, double& du, double& du2)
|
||||||
|
{
|
||||||
|
du = 0.0;
|
||||||
|
du2 = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
void hessian_twobody(double fforce, double dfac, double delr[3], double phiTensor[6]);
|
void hessian_twobody(double fforce, double dfac, double delr[3], double phiTensor[6]);
|
||||||
|
|
||||||
virtual double single_hessian(int, int, int, int, double, double[3], double, double,
|
virtual double single_hessian(int, int, int, int, double, double[3], double, double,
|
||||||
|
|||||||
@ -40,6 +40,7 @@ using namespace MathConst;
|
|||||||
PairLJCut::PairLJCut(LAMMPS *lmp) : Pair(lmp)
|
PairLJCut::PairLJCut(LAMMPS *lmp) : Pair(lmp)
|
||||||
{
|
{
|
||||||
respa_enable = 1;
|
respa_enable = 1;
|
||||||
|
born_enable = 1;
|
||||||
writedata = 1;
|
writedata = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,6 +681,28 @@ double PairLJCut::single(int /*i*/, int /*j*/, int itype, int jtype, double rsq,
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void PairLJCut::born(int /*i*/, int /*j*/, int itype, int jtype, double rsq,
|
||||||
|
double /*factor_coul*/, double factor_lj,
|
||||||
|
double &dupair, double &du2pair)
|
||||||
|
{
|
||||||
|
double rinv,r2inv,r6inv,du,du2;
|
||||||
|
|
||||||
|
r2inv = 1.0/rsq;
|
||||||
|
rinv = sqrt(r2inv);
|
||||||
|
r6inv = r2inv*r2inv*r2inv;
|
||||||
|
|
||||||
|
// Reminder: lj1 = 48*e*s^12, lj2 = 24*e*s^6
|
||||||
|
// so dupair = -forcelj/r = -fforce*r (forcelj from single method)
|
||||||
|
|
||||||
|
du = r6inv * rinv * (lj2[itype][jtype] - lj1[itype][jtype]*r6inv);
|
||||||
|
du2 = r6inv * r2inv * (13*lj1[itype][jtype]*r6inv - 7*lj2[itype][jtype]);
|
||||||
|
|
||||||
|
dupair = factor_lj*du;
|
||||||
|
du2pair = factor_lj*du2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void *PairLJCut::extract(const char *str, int &dim)
|
void *PairLJCut::extract(const char *str, int &dim)
|
||||||
{
|
{
|
||||||
dim = 2;
|
dim = 2;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ class PairLJCut : public Pair {
|
|||||||
void write_data(FILE *);
|
void write_data(FILE *);
|
||||||
void write_data_all(FILE *);
|
void write_data_all(FILE *);
|
||||||
double single(int, int, int, int, double, double, double, double &);
|
double single(int, int, int, int, double, double, double, double &);
|
||||||
|
void born(int, int, int, int, double, double, double, double &, double &);
|
||||||
void *extract(const char *, int &);
|
void *extract(const char *, int &);
|
||||||
|
|
||||||
void compute_inner();
|
void compute_inner();
|
||||||
|
|||||||
Reference in New Issue
Block a user