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

This commit is contained in:
sjplimp 2010-10-26 16:14:31 +00:00
parent c2723c7d27
commit bfd6a79fe6
52 changed files with 16864 additions and 0 deletions

115
src/USER-REAXC/Install.sh Executable file
View File

@ -0,0 +1,115 @@
# Install/unInstall package classes in LAMMPS
if (test $1 = 1) then
cp -p pair_reax_c.cpp ..
cp -p fix_qeq_reax.cpp ..
cp -p fix_reax_c.cpp ..
cp -p pair_reax_c.h ..
cp -p fix_qeq_reax.h ..
cp -p fix_reax_c.h ..
cp -p reaxc_allocate.cpp ..
cp -p reaxc_basic_comm.cpp ..
cp -p reaxc_bond_orders.cpp ..
cp -p reaxc_bonds.cpp ..
cp -p reaxc_control.cpp ..
cp -p reaxc_ffield.cpp ..
cp -p reaxc_forces.cpp ..
cp -p reaxc_hydrogen_bonds.cpp ..
cp -p reaxc_init_md.cpp ..
cp -p reaxc_io_tools.cpp ..
cp -p reaxc_list.cpp ..
cp -p reaxc_lookup.cpp ..
cp -p reaxc_multi_body.cpp ..
cp -p reaxc_nonbonded.cpp ..
cp -p reaxc_reset_tools.cpp ..
cp -p reaxc_system_props.cpp ..
cp -p reaxc_tool_box.cpp ..
cp -p reaxc_torsion_angles.cpp ..
cp -p reaxc_traj.cpp ..
cp -p reaxc_valence_angles.cpp ..
cp -p reaxc_vector.cpp ..
cp -p reaxc_allocate.h ..
cp -p reaxc_basic_comm.h ..
cp -p reaxc_bond_orders.h ..
cp -p reaxc_bonds.h ..
cp -p reaxc_control.h ..
cp -p reaxc_defs.h ..
cp -p reaxc_ffield.h ..
cp -p reaxc_forces.h ..
cp -p reaxc_hydrogen_bonds.h ..
cp -p reaxc_init_md.h ..
cp -p reaxc_io_tools.h ..
cp -p reaxc_list.h ..
cp -p reaxc_lookup.h ..
cp -p reaxc_multi_body.h ..
cp -p reaxc_nonbonded.h ..
cp -p reaxc_reset_tools.h ..
cp -p reaxc_system_props.h ..
cp -p reaxc_tool_box.h ..
cp -p reaxc_torsion_angles.h ..
cp -p reaxc_traj.h ..
cp -p reaxc_types.h ..
cp -p reaxc_valence_angles.h ..
cp -p reaxc_vector.h ..
elif (test $1 = 0) then
rm ../pair_reax_c.cpp
rm ../fix_qeq_reax.cpp
rm ../fix_reax_c.cpp
rm ../pair_reax_c.h
rm ../fix_qeq_reax.h
rm ../fix_reax_c.h
rm ../reaxc_allocate.cpp
rm ../reaxc_basic_comm.cpp
rm ../reaxc_bond_orders.cpp
rm ../reaxc_bonds.cpp
rm ../reaxc_control.cpp
rm ../reaxc_ffield.cpp
rm ../reaxc_forces.cpp
rm ../reaxc_hydrogen_bonds.cpp
rm ../reaxc_init_md.cpp
rm ../reaxc_io_tools.cpp
rm ../reaxc_list.cpp
rm ../reaxc_lookup.cpp
rm ../reaxc_multi_body.cpp
rm ../reaxc_nonbonded.cpp
rm ../reaxc_reset_tools.cpp
rm ../reaxc_system_props.cpp
rm ../reaxc_tool_box.cpp
rm ../reaxc_torsion_angles.cpp
rm ../reaxc_traj.cpp
rm ../reaxc_valence_angles.cpp
rm ../reaxc_vector.cpp
rm ../reaxc_allocate.h
rm ../reaxc_basic_comm.h
rm ../reaxc_bond_orders.h
rm ../reaxc_bonds.h
rm ../reaxc_control.h
rm ../reaxc_defs.h
rm ../reaxc_ffield.h
rm ../reaxc_forces.h
rm ../reaxc_hydrogen_bonds.h
rm ../reaxc_init_md.h
rm ../reaxc_io_tools.h
rm ../reaxc_list.h
rm ../reaxc_lookup.h
rm ../reaxc_multi_body.h
rm ../reaxc_nonbonded.h
rm ../reaxc_reset_tools.h
rm ../reaxc_system_props.h
rm ../reaxc_tool_box.h
rm ../reaxc_torsion_angles.h
rm ../reaxc_traj.h
rm ../reaxc_types.h
rm ../reaxc_valence_angles.h
rm ../reaxc_vector.h
fi

61
src/USER-REAXC/README Normal file
View File

@ -0,0 +1,61 @@
The files in this directory are a user-contributed package for LAMMPS.
The person who created this package is Hasan Metin Aktulga, haktulga
at cs.purdue.edu, while at Purdue University. Contact him directly,
or Aidan Thompson (Sandia) at athomps at sandia.gov, if you have
questions.
--------------------------------------
Note that the files with names starting with "reaxc" in this package
are from PuReMD, the Purdue ReaxFF Molecular Dynamics Program. Its
copyright info and authorship info are listed below.
PACKAGE DESCRIPTION:
Contains a implementation for LAMMPS of the ReaxFF force field.
ReaxFF uses distance-dependent bond-order functions to represent the
contributions of chemical bonding to the potential energy. It was
originally developed by Adri van Duin and the Goddard group at
CalTech.
The USER-REAXC version of ReaxFF (pair_style reax/c), implemented in
C++, should give identical or very similar results to pair_style reax,
which is a ReaxFF implementation on top of a Fortran library, a
version of which was originally authored by Adri van Duin.
The reax/c version should be somewhat faster and more scalable,
particularly with respect to the charge equilibration calculation. It
should also be easier to build and use since there are no complicating
issues due to linking to a Fortran library.
OTHERS FILES INCLUDED:
User examples for pair_style reax/c are in examples/reax.
Thanks to Steve Plimpton and Aidan Thompson for their input on the
LAMMPS architecture and for their help in understanding and
customizing some of the required LAMMPS interfaces.
--------------------------------------
The reaxc files in this directory have the following header:
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,851 @@
/* ----------------------------------------------------------------------
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: Hasan Metin Aktulga, Purdue University
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_qeq_reax.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EV_TO_KCAL_PER_MOL 14.4
#define SAFE_ZONE 1.2
#define DANGER_ZONE 0.95
#define LOOSE_ZONE 0.7
#define SQR(x) ((x)*(x))
#define CUBE(x) ((x)*(x)*(x))
#define MIN_CAP 50
#define MIN_NBRS 100
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
/* ---------------------------------------------------------------------- */
FixQEqReax::FixQEqReax(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (narg != 8) error->all("Illegal fix qeq/reax command");
nevery = atoi(arg[3]);
swa = atof(arg[4]);
swb = atof(arg[5]);
tolerance = atof(arg[6]);
pertype_parameters(arg[7]);
shld = NULL;
n = n_cap = 0;
N = nmax = 0;
m_fill = m_cap = 0;
pack_flag = 0;
s = NULL;
t = NULL;
nprev = 5;
Hdia_inv = NULL;
b_s = NULL;
b_t = NULL;
b_prc = NULL;
b_prm = NULL;
// CG
p = NULL;
q = NULL;
r = NULL;
d = NULL;
// GMRES
//g = NULL;
//y = NULL;
//hstr = NULL;
//v = NULL;
//h = NULL;
//hc = NULL;
//hs = NULL;
// perform initial allocation of atom-based arrays
// register with Atom class
s_hist = t_hist = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
for( int i = 0; i < atom->nmax; i++ )
for (int j = 0; j < nprev; ++j )
s_hist[i][j] = t_hist[i][j] = 0;
}
/* ---------------------------------------------------------------------- */
FixQEqReax::~FixQEqReax()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
memory->destroy_2d_double_array(s_hist);
memory->destroy_2d_double_array(t_hist);
deallocate_storage();
deallocate_matrix();
memory->destroy_2d_double_array(shld);
if (!reaxflag) {
memory->sfree(chi);
memory->sfree(eta);
memory->sfree(gamma);
}
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::setmask()
{
int mask = 0;
mask |= PRE_FORCE;
mask |= MIN_PRE_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pertype_parameters(char *arg)
{
if (strcmp(arg,"reax/c") == 0) {
reaxflag = 1;
Pair *pair = force->pair_match("reax/c",1);
if (pair == NULL) error->all("No pair reax/c for fix qeq/reax");
int tmp;
chi = (double *) pair->extract("chi",tmp);
eta = (double *) pair->extract("eta",tmp);
gamma = (double *) pair->extract("gamma",tmp);
if (chi == NULL || eta == NULL || gamma == NULL)
error->all("Fix qeq/reax could not extract params from pair reax/c");
return;
}
int i,itype,ntypes;
double v1,v2,v3;
FILE *pf;
reaxflag = 0;
ntypes = atom->ntypes;
chi = (double*) memory->smalloc(sizeof(double)*(ntypes+1),"qeq/reax:chi");
eta = (double*) memory->smalloc(sizeof(double)*(ntypes+1),"qeq/reax:eta");
gamma = (double*) memory->smalloc(sizeof(double)*(ntypes+1),
"qeq/reax:gamma");
if (comm->me == 0) {
if ((pf = fopen(arg,"r")) == NULL)
error->one("Fix qeq/reax parameter file could not be found");
for (i = 1; i <= ntypes && !feof(pf); i++) {
fscanf(pf,"%d %lg %lg %lg",&itype,&v1,&v2,&v3);
if (itype < 1 || itype > ntypes)
error->one("Fix qeq/reax invalid atom type in param file");
chi[itype] = v1;
eta[itype] = v2;
gamma[itype] = v3;
}
if (i <= ntypes) error->one("Invalid param file for fix qeq/reax");
fclose(pf);
}
MPI_Bcast(&chi[1],ntypes,MPI_DOUBLE,0,world);
MPI_Bcast(&eta[1],ntypes,MPI_DOUBLE,0,world);
MPI_Bcast(&gamma[1],ntypes,MPI_DOUBLE,0,world);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::allocate_storage()
{
nmax = atom->nmax;
s = (double*) memory->smalloc( nmax * sizeof(double), "qeq:s" );
t = (double*) memory->smalloc( nmax * sizeof(double), "qeq:t" );
Hdia_inv = (double*) memory->smalloc(nmax * sizeof(double), "qeq:Hdia_inv");
b_s = (double*) memory->smalloc( nmax * sizeof(double), "qeq:b_s" );
b_t = (double*) memory->smalloc( nmax * sizeof(double), "qeq:b_t" );
b_prc = (double*) memory->smalloc( nmax * sizeof(double), "qeq:b_prc" );
b_prm = (double*) memory->smalloc( nmax * sizeof(double), "qeq:b_prm" );
// CG
p = (double*) memory->smalloc( nmax * sizeof(double), "qeq:p" );
q = (double*) memory->smalloc( nmax * sizeof(double), "qeq:q" );
r = (double*) memory->smalloc( nmax * sizeof(double), "qeq:r" );
d = (double*) memory->smalloc( nmax * sizeof(double), "qeq:d" );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::deallocate_storage()
{
memory->sfree(s);
memory->sfree(t);
memory->sfree( Hdia_inv );
memory->sfree( b_s );
memory->sfree( b_t );
memory->sfree( b_prc );
memory->sfree( b_prm );
memory->sfree( p );
memory->sfree( q );
memory->sfree( r );
memory->sfree( d );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::reallocate_storage()
{
deallocate_storage();
allocate_storage();
init_storage();
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::allocate_matrix()
{
int i,ii;
n = atom->nlocal;
n_cap = MAX( (int)(n * SAFE_ZONE), MIN_CAP );
// determine the total space for the H matrix
int m = 0;
for( ii = 0; ii < list->inum; ii++ ) {
i = list->ilist[ii];
m += list->numneigh[i];
}
m_cap = MAX( (int)(m * SAFE_ZONE), MIN_CAP * MIN_NBRS );
H.n = n_cap;
H.m = m_cap;
H.firstnbr = (int*) memory->smalloc( n_cap * sizeof(int), "qeq:H.firstnbr" );
H.numnbrs = (int*) memory->smalloc( n_cap * sizeof(int), "qeq:H.numnbrs" );
H.jlist = (int*) memory->smalloc( m_cap * sizeof(int), "qeq:H.jlist" );
H.val = (double*) memory->smalloc( m_cap * sizeof(double), "qeq:H.val" );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::deallocate_matrix()
{
memory->sfree( H.firstnbr );
memory->sfree( H.numnbrs );
memory->sfree( H.jlist );
memory->sfree( H.val );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::reallocate_matrix()
{
deallocate_matrix();
allocate_matrix();
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init()
{
if (!atom->q_flag) error->all("Fix qeq/reax requires atom attribute q");
// need a half neighbor list w/ Newton off
// built whenever re-neighboring occurs
int irequest = neighbor->request(this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->newton = 2;
init_shielding();
init_taper();
if (strcmp(update->integrate_style,"respa") == 0)
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_shielding()
{
int i,j;
int ntypes;
ntypes = atom->ntypes;
shld = memory->create_2d_double_array(ntypes+1, ntypes+1, "qeq:shileding");
for( i = 1; i <= ntypes; ++i )
for( j = 1; j <= ntypes; ++j )
shld[i][j] = pow( gamma[i] * gamma[j], -1.5 );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_taper()
{
double d7, swa2, swa3, swb2, swb3;
if (fabs(swa) > 0.01 && comm->me == 0)
error->warning("Fix qeq/reax has non-zero lower Taper radius cutoff");
if (swb < 0)
error->all( "Fix qeq/reax has negative upper Taper radius cutoff");
else if (swb < 5 && comm->me == 0)
error->warning("Fix qeq/reax has very low Taper radius cutoff");
d7 = pow( swb - swa, 7 );
swa2 = SQR( swa );
swa3 = CUBE( swa );
swb2 = SQR( swb );
swb3 = CUBE( swb );
Tap[7] = 20.0 / d7;
Tap[6] = -70.0 * (swa + swb) / d7;
Tap[5] = 84.0 * (swa2 + 3.0*swa*swb + swb2) / d7;
Tap[4] = -35.0 * (swa3 + 9.0*swa2*swb + 9.0*swa*swb2 + swb3 ) / d7;
Tap[3] = 140.0 * (swa3*swb + 3.0*swa2*swb2 + swa*swb3 ) / d7;
Tap[2] =-210.0 * (swa3*swb2 + swa2*swb3) / d7;
Tap[1] = 140.0 * swa3 * swb3 / d7;
Tap[0] = (-35.0*swa3*swb2*swb2 + 21.0*swa2*swb3*swb2 +
7.0*swa*swb3*swb3 + swb3*swb3*swb ) / d7;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::setup_pre_force(int vflag)
{
neighbor->build_one(list->index);
allocate_storage();
init_storage();
allocate_matrix();
pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::setup_pre_force_respa(int vflag, int ilevel)
{
if (ilevel < nlevels_respa-1) return;
setup_pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::min_setup_pre_force(int vflag)
{
setup_pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_storage()
{
N = atom->nlocal + atom->nghost;
for( int i = 0; i < N; i++ ) {
Hdia_inv[i] = 1. / eta[atom->type[i]];
b_s[i] = -chi[atom->type[i]];
b_t[i] = -1.0;
b_prc[i] = 0;
b_prm[i] = 0;
s[i] = t[i] = 0;
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pre_force(int vflag)
{
double t_start, t_end;
if (update->ntimestep % nevery) return;
if( comm->me == 0 ) t_start = MPI_Wtime();
n = atom->nlocal;
N = atom->nlocal + atom->nghost;
// grow arrays if necessary
// need to be atom->nmax in length
if( atom->nmax > nmax ) reallocate_storage();
if( n > n_cap*DANGER_ZONE || m_fill > m_cap*DANGER_ZONE )
reallocate_matrix();
init_matvec();
matvecs = CG(b_s, s); // CG on s - parallel
matvecs += CG(b_t, t); // CG on t - parallel
calculate_Q();
if( comm->me == 0 ) {
t_end = MPI_Wtime();
qeq_time = t_end - t_start;
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pre_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::min_pre_force(int vflag)
{
pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_matvec()
{
/* fill-in H matrix */
compute_H();
for( int i = 0; i < n; ++i ) {
/* init pre-conditioner for H and init solution vectors */
Hdia_inv[i] = 1. / eta[ atom->type[i] ];
b_s[i] = -chi[ atom->type[i] ];
b_t[i] = -1.0;
/* linear extrapolation for s & t from previous solutions */
//s[i] = 2 * s_hist[i][0] - s_hist[i][1];
//t[i] = 2 * t_hist[i][0] - t_hist[i][1];
/* quadratic extrapolation for s & t from previous solutions */
//s[i] = s_hist[i][2] + 3 * ( s_hist[i][0] - s_hist[i][1] );
t[i] = t_hist[i][2] + 3 * ( t_hist[i][0] - t_hist[i][1] );
/* cubic extrapolation for s & t from previous solutions */
s[i] = 4*(s_hist[i][0]+s_hist[i][2])-(6*s_hist[i][1]+s_hist[i][3]);
//t[i] = 4*(t_hist[i][0]+t_hist[i][2])-(6*t_hist[i][1]+t_hist[i][3]);
}
pack_flag = 2;
comm->forward_comm_fix(this); //Dist_vector( s );
pack_flag = 3;
comm->forward_comm_fix(this); //Dist_vector( t );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::compute_H()
{
int inum, jnum, *ilist, *jlist, *numneigh, **firstneigh;
int i, j, ii, jj, temp, newnbr;
int *type;
double **x;
double dx, dy, dz, r_sqr;
type = atom->type;
x = atom->x;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// fill in the H matrix
m_fill = 0;
r_sqr = 0;
for( ii = 0; ii < inum; ii++ ) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
H.firstnbr[i] = m_fill;
for( jj = 0; jj < jnum; jj++ ) {
j = jlist[jj];
dx = x[i][0] - x[j][0];
dy = x[i][1] - x[j][1];
dz = x[i][2] - x[j][2];
r_sqr = SQR(dx) + SQR(dy) + SQR(dz);
if( r_sqr <= SQR(swb) && (j < n || atom->tag[i] <= atom->tag[j]) ) {
H.jlist[m_fill] = j;
H.val[m_fill] = calculate_H( sqrt(r_sqr), shld[type[i]][type[j]] );
m_fill++;
}
}
H.numnbrs[i] = m_fill - H.firstnbr[i];
}
if (m_fill >= H.m) {
char str[128];
sprintf(str,"H matrix size has been exceeded: m_fill=%d H.m=%d\n",
m_fill, H.m );
error->warning(str);
error->all("Fix qeq/reax has insufficient QEq matrix size");
}
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::calculate_H( double r, double gamma )
{
double Taper, denom;
Taper = Tap[7] * r + Tap[6];
Taper = Taper * r + Tap[5];
Taper = Taper * r + Tap[4];
Taper = Taper * r + Tap[3];
Taper = Taper * r + Tap[2];
Taper = Taper * r + Tap[1];
Taper = Taper * r + Tap[0];
denom = r * r * r + gamma;
denom = pow(denom,0.3333333333333);
return Taper * EV_TO_KCAL_PER_MOL / denom;
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::CG( double *b, double *x )
{
int i, j;
double tmp, alpha, beta, b_norm;
double sig_old, sig_new, sig0;
pack_flag = 1;
sparse_matvec( &H, x, q );
comm->reverse_comm_fix( this ); //Coll_Vector( q );
vector_sum( r , 1., b, -1., q, n );
for( j = 0; j < n; ++j )
d[j] = r[j] * Hdia_inv[j]; //pre-condition
b_norm = parallel_norm( b, n );
sig_new = parallel_dot( r, d, n );
sig0 = sig_new;
for( i = 1; i < 100 && sqrt(sig_new) / b_norm > tolerance; ++i ) {
comm->forward_comm_fix(this); //Dist_vector( d );
sparse_matvec( &H, d, q );
comm->reverse_comm_fix(this); //Coll_vector( q );
tmp = parallel_dot( d, q, n );
alpha = sig_new / tmp;
// comm->me, i, parallel_norm( d, n ), parallel_norm( q, n ), tmp );
vector_add( x, alpha, d, n );
vector_add( r, -alpha, q, n );
// pre-conditioning
for( j = 0; j < n; ++j )
p[j] = r[j] * Hdia_inv[j];
sig_old = sig_new;
sig_new = parallel_dot( r, p, n );
beta = sig_new / sig_old;
vector_sum( d, 1., p, beta, d, n );
}
if (i >= 100 && comm->me == 0)
error->warning("Fix qeq/reax CG convergence failed");
return i;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::sparse_matvec( sparse_matrix *A, double *x, double *b )
{
int i, j, itr_j;
for( i = 0; i < n; ++i )
b[i] = eta[ atom->type[i] ] * x[i];
for( i = n; i < N; ++i )
b[i] = 0;
for( i = 0; i < n; ++i ) {
for( itr_j=A->firstnbr[i]; itr_j<A->firstnbr[i]+A->numnbrs[i]; itr_j++) {
j = A->jlist[itr_j];
b[i] += A->val[itr_j] * x[j];
b[j] += A->val[itr_j] * x[i];
}
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::calculate_Q()
{
int i, k;
double u, s_sum, t_sum;
double *q = atom->q;
s_sum = parallel_vector_acc( s, n );
t_sum = parallel_vector_acc( t, n);
u = s_sum / t_sum;
for( i = 0; i < n; ++i ) {
q[i] = s[i] - u * t[i];
/* backup s & t */
for( k = 4; k > 0; --k ) {
s_hist[i][k] = s_hist[i][k-1];
t_hist[i][k] = t_hist[i][k-1];
}
s_hist[i][0] = s[i];
t_hist[i][0] = t[i];
}
pack_flag = 4;
comm->forward_comm_fix( this ); //Dist_vector( atom->q );
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int m;
if( pack_flag == 1)
for(m = 0; m < n; m++) buf[m] = d[list[m]];
else if( pack_flag == 2 )
for(m = 0; m < n; m++) buf[m] = s[list[m]];
else if( pack_flag == 3 )
for(m = 0; m < n; m++) buf[m] = t[list[m]];
else if( pack_flag == 4 )
for(m = 0; m < n; m++) buf[m] = atom->q[list[m]];
return 1;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::unpack_comm(int n, int first, double *buf)
{
int i, m;
if( pack_flag == 1)
for(m = 0, i = first; m < n; m++, i++) d[i] = buf[m];
else if( pack_flag == 2)
for(m = 0, i = first; m < n; m++, i++) s[i] = buf[m];
else if( pack_flag == 3)
for(m = 0, i = first; m < n; m++, i++) t[i] = buf[m];
else if( pack_flag == 4)
for(m = 0, i = first; m < n; m++, i++) atom->q[i] = buf[m];
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::pack_reverse_comm(int n, int first, double *buf)
{
int i, m;
for(m = 0, i = first; m < n; m++, i++) buf[m] = q[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::unpack_reverse_comm(int n, int *list, double *buf)
{
for(int m = 0; m < n; m++) q[list[m]] += buf[m];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixQEqReax::memory_usage()
{
double bytes;
bytes = atom->nmax*nprev*2 * sizeof(double); // s_hist & t_hist
bytes += atom->nmax*11 * sizeof(double); // storage
bytes += n_cap*2 * sizeof(int); // matrix...
bytes += m_cap * sizeof(int);
bytes += m_cap * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate fictitious charge arrays
------------------------------------------------------------------------- */
void FixQEqReax::grow_arrays(int nmax)
{
s_hist = memory->grow_2d_double_array(s_hist,nmax,nprev,"qeq:s_hist");
t_hist = memory->grow_2d_double_array(t_hist,nmax,nprev,"qeq:t_hist");
}
/* ----------------------------------------------------------------------
copy values within fictitious charge arrays
------------------------------------------------------------------------- */
void FixQEqReax::copy_arrays(int i, int j)
{
for (int m = 0; m < nprev; m++) {
s_hist[j][m] = s_hist[i][m];
t_hist[j][m] = t_hist[i][m];
}
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixQEqReax::pack_exchange(int i, double *buf)
{
for (int m = 0; m < nprev; m++) buf[m] = s_hist[i][m];
for (int m = 0; m < nprev; m++) buf[nprev+m] = t_hist[i][m];
return nprev*2;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixQEqReax::unpack_exchange(int nlocal, double *buf)
{
for (int m = 0; m < nprev; m++) s_hist[nlocal][m] = buf[m];
for (int m = 0; m < nprev; m++) t_hist[nlocal][m] = buf[nprev+m];
return nprev*2;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_norm( double *v, int n )
{
int i;
double my_sum, norm_sqr;
my_sum = 0;
for( i = 0; i < n; ++i )
my_sum += SQR( v[i] );
MPI_Allreduce( &my_sum, &norm_sqr, 1, MPI_DOUBLE, MPI_SUM, world );
return sqrt( norm_sqr );
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_dot( double *v1, double *v2, int n )
{
int i;
double my_dot, res;
my_dot = 0;
res = 0;
for( i = 0; i < n; ++i )
my_dot += v1[i] * v2[i];
MPI_Allreduce( &my_dot, &res, 1, MPI_DOUBLE, MPI_SUM, world );
return res;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_vector_acc( double *v, int n )
{
int i;
double my_acc, res;
my_acc = 0;
for( i = 0; i < n; ++i )
my_acc += v[i];
MPI_Allreduce( &my_acc, &res, 1, MPI_DOUBLE, MPI_SUM, world );
return res;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::norm( double* v1, int k )
{
double ret = 0;
for( --k; k>=0; --k )
ret += ( v1[k] * v1[k] );
return sqrt( ret );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_sum( double* dest, double c, double* v,
double d, double* y, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k] + d * y[k];
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_scale( double* dest, double c, double* v, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k];
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::dot( double* v1, double* v2, int k )
{
double ret = 0;
for( --k; k>=0; --k )
ret += v1[k] * v2[k];
return ret;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_add( double* dest, double c, double* v, int k )
{
for( --k; k>=0; --k )
dest[k] += c * v[k];
}

View File

@ -0,0 +1,134 @@
/* ----------------------------------------------------------------------
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(qeq/reax,FixQEqReax)
#else
#ifndef LMP_FIX_QEQ_REAX_H
#define LMP_FIX_QEQ_REAX_H
#include "fix.h"
namespace LAMMPS_NS {
class FixQEqReax : public Fix {
public:
FixQEqReax(class LAMMPS *, int, char **);
~FixQEqReax();
int setmask();
void init();
void init_list(int,class NeighList *);
void init_storage();
void setup_pre_force(int);
void pre_force(int);
void setup_pre_force_respa(int, int);
void pre_force_respa(int, int, int);
void min_setup_pre_force(int);
void min_pre_force(int);
int matvecs;
double qeq_time;
private:
int nevery,reaxflag;
int n, N, m_fill;
int n_cap, nmax, m_cap;
int pack_flag;
int nlevels_respa;
class NeighList *list;
double swa, swb; // lower/upper Taper cutoff radius
double Tap[8]; // Taper function
double tolerance; // tolerance for the norm of the rel residual in CG
double *chi,*eta,*gamma; // qeq parameters
double **shld;
// fictitious charges
double *s, *t;
double **s_hist, **t_hist;
int nprev;
typedef struct{
int n, m;
int *firstnbr;
int *numnbrs;
int *jlist;
double *val;
} sparse_matrix;
sparse_matrix H;
double *Hdia_inv;
double *b_s, *b_t;
double *b_prc, *b_prm;
//CG storage
double *p, *q, *r, *d;
//GMRES storage
//double *g,*y;
//double **v;
//double **h;
//double *hc, *hs;
void pertype_parameters(char*);
void init_shielding();
void init_taper();
void allocate_storage();
void deallocate_storage();
void reallocate_storage();
void allocate_matrix();
void deallocate_matrix();
void reallocate_matrix();
void init_matvec();
void init_H();
void compute_H();
double calculate_H(double,double);
void calculate_Q();
int CG(double*,double*);
//int GMRES(double*,double*);
void sparse_matvec(sparse_matrix*,double*,double*);
int pack_comm(int, int *, double *, int, int *);
void unpack_comm(int, int, double *);
int pack_reverse_comm(int, int, double *);
void unpack_reverse_comm(int, int *, double *);
double memory_usage();
void grow_arrays(int);
void copy_arrays(int, int);
int pack_exchange(int, double *);
int unpack_exchange(int, double *);
double parallel_norm( double*, int );
double parallel_dot( double*, double*, int );
double parallel_vector_acc( double*, int );
double norm(double*,int);
void vector_sum(double*,double,double*,double,double*,int);
void vector_scale(double*,double,double*,int);
double dot(double*,double*,int);
void vector_add(double*, double, double*,int);
};
}
#endif
#endif

View File

@ -0,0 +1,156 @@
/* ----------------------------------------------------------------------
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: Hasan Metin Aktulga, Purdue University
------------------------------------------------------------------------- */
#include "fix_reax_c.h"
#include "atom.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define MAX_REAX_BONDS 30
#define MIN_REAX_BONDS 15
#define MIN_REAX_HBONDS 25
/* ---------------------------------------------------------------------- */
FixReaxC::FixReaxC(LAMMPS *lmp,int narg, char **arg) :
Fix(lmp, narg, arg)
{
// perform initial allocation of atom-based arrays
// register with atom class
num_bonds = NULL;
num_hbonds = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// initialize arrays to MIN so atom migration is OK the 1st time
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
num_bonds[i] = num_hbonds[i] = MIN_REAX_BONDS;
// set comm sizes needed by this fix
comm_forward = 1;
}
/* ---------------------------------------------------------------------- */
FixReaxC::~FixReaxC()
{
// unregister this fix so atom class doesn't invoke it any more
atom->delete_callback(id,0);
// delete locally stored arrays
memory->sfree(num_bonds);
memory->sfree(num_hbonds);
}
/* ---------------------------------------------------------------------- */
int FixReaxC::setmask()
{
int mask = 0;
return mask;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixReaxC::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * 2 * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixReaxC::grow_arrays(int nmax)
{
num_bonds = (int *) memory->srealloc(num_bonds,nmax*sizeof(int),
"reaxc:num_bonds");
num_hbonds = (int *) memory->srealloc(num_hbonds,nmax*sizeof(int),
"reaxc:num_hbonds");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixReaxC::copy_arrays(int i, int j)
{
num_bonds[j] = num_bonds[i];
num_hbonds[j] = num_hbonds[i];
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixReaxC::pack_exchange(int i, double *buf)
{
buf[0] = num_bonds[i];
buf[1] = num_hbonds[i];
return 2;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixReaxC::unpack_exchange(int nlocal, double *buf)
{
num_bonds[nlocal] = static_cast<int> (buf[0]);
num_hbonds[nlocal] = static_cast<int> (buf[1]);
return 2;
}
/* ---------------------------------------------------------------------- */
int FixReaxC::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = num_bonds[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void FixReaxC::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
num_bonds[i] = buf[m++];
}

View File

@ -0,0 +1,53 @@
/* ----------------------------------------------------------------------
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(REAXC,FixReaxC)
#else
#ifndef LMP_FIX_REAXC_H
#define LMP_FIX_REAXC_H
#include "fix.h"
namespace LAMMPS_NS {
class FixReaxC : public Fix {
friend class PairReaxC;
public:
FixReaxC(class LAMMPS *,int, char **);
~FixReaxC();
int setmask();
double memory_usage();
void grow_arrays(int);
void copy_arrays(int, int);
int pack_exchange(int, double *);
int unpack_exchange(int, double *);
int pack_comm(int, int *, double *, int, int *);
void unpack_comm(int, int, double *);
private:
int maxbonds; // max # of bonds for any atom
int maxhbonds; // max # of Hbonds for any atom
int *num_bonds; // # of bonds for each atom
int *num_hbonds; // # of Hbonds for each atom
};
}
#endif
#endif

View File

@ -0,0 +1,664 @@
/* ----------------------------------------------------------------------
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: Hasan Metin Aktulga, Purdue University
------------------------------------------------------------------------- */
#include "pair_reax_c.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "modify.h"
#include "fix.h"
#include "fix_reax_c.h"
#include "memory.h"
#include "error.h"
#include "reaxc_types.h"
#include "reaxc_allocate.h"
#include "reaxc_control.h"
#include "reaxc_ffield.h"
#include "reaxc_forces.h"
#include "reaxc_init_md.h"
#include "reaxc_io_tools.h"
#include "reaxc_list.h"
#include "reaxc_lookup.h"
#include "reaxc_reset_tools.h"
#include "reaxc_traj.h"
#include "reaxc_vector.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairReaxC::PairReaxC(LAMMPS *lmp) : Pair(lmp)
{
system = (reax_system *)
memory->smalloc( sizeof(reax_system), "reax:system" );
control = (control_params *)
memory->smalloc( sizeof(control_params), "reax:control" );
data = (simulation_data *)
memory->smalloc( sizeof(simulation_data), "reax:data" );
workspace = (storage *)
memory->smalloc( sizeof(storage), "reax:storage" );
lists = (reax_list *)
memory->smalloc( LIST_N * sizeof(reax_list), "reax:lists" );
out_control = (output_controls *)
memory->smalloc( sizeof(output_controls), "reax:out_control" );
mpi_data = (mpi_datatypes *)
memory->smalloc( sizeof(mpi_datatypes), "reax:mpi");
MPI_Comm_rank(world, &system->my_rank);
system->my_coords[0] = 0;
system->my_coords[1] = 0;
system->my_coords[2] = 0;
system->num_nbrs = 0;
system->n = 0; // my atoms
system->N = 0; // mine + ghosts
system->bigN = 0; // all atoms in the system
system->local_cap = 0;
system->total_cap = 0;
system->gcell_cap = 0;
system->bndry_cuts.ghost_nonb = 0;
system->bndry_cuts.ghost_hbond = 0;
system->bndry_cuts.ghost_bond = 0;
system->bndry_cuts.ghost_cutoff = 0;
system->my_atoms = NULL;
fix_reax = NULL;
}
/* ---------------------------------------------------------------------- */
PairReaxC::~PairReaxC()
{
if (fix_reax) modify->delete_fix("REAXC");
Close_Output_Files( system, control, out_control, mpi_data );
// deallocate reax data-structures
if( control->tabulate ) Deallocate_Lookup_Tables( system );
if( control->hbond_cut > 0 ) Delete_List( lists+HBONDS, world );
Delete_List( lists+BONDS, world );
Delete_List( lists+THREE_BODIES, world );
Delete_List( lists+FAR_NBRS, world );
// fprintf( stderr, "3\n" );
DeAllocate_Workspace( control, workspace );
DeAllocate_System( system );
//fprintf( stderr, "4\n" );
memory->sfree( system );
memory->sfree( control );
memory->sfree( data );
memory->sfree( workspace );
memory->sfree( lists );
memory->sfree( out_control );
memory->sfree( mpi_data );
//fprintf( stderr, "5\n" );
// deallocate interface storage
if( allocated ) {
memory->destroy_2d_int_array(setflag);
memory->destroy_2d_double_array(cutsq);
delete [] map;
delete [] chi;
delete [] eta;
delete [] gamma;
}
//fprintf( stderr, "6\n" );
}
/* ---------------------------------------------------------------------- */
void PairReaxC::allocate( )
{
allocated = 1;
int n = atom->ntypes;
setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
map = new int[n+1];
chi = new double[n+1];
eta = new double[n+1];
gamma = new double[n+1];
}
/* ---------------------------------------------------------------------- */
void PairReaxC::settings(int narg, char **arg)
{
if (narg != 1) error->all("Illegal pair_style command");
if (strcmp(arg[0],"NULL") == 0) {
strcpy( control->sim_name, "simulate" );
control->ensemble = 0;
out_control->energy_update_freq = 0;
control->tabulate = 0;
control->reneighbor = 1;
control->vlist_cut = control->nonb_cut;
control->bond_cut = 5.;
control->hbond_cut = 7.50;
control->thb_cut = 0.001;
out_control->write_steps = 0;
out_control->traj_method = 0;
strcpy( out_control->traj_title, "default_title" );
out_control->atom_info = 0;
out_control->bond_info = 0;
out_control->angle_info = 0;
} else Read_Control_File(arg[0], control, out_control);
// LAMMPS is responsible for generating nbrs
control->reneighbor = 1;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::coeff( int nargs, char **args )
{
if (!allocated) allocate();
if (nargs != 3 + atom->ntypes)
error->all("Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(args[0],"*") != 0 || strcmp(args[1],"*") != 0)
error->all("Incorrect args for pair coefficients");
// read ffield file
Read_Force_Field(args[2], &(system->reax_param), control);
// read args that map atom types to elements in potential file
// map[i] = which element the Ith atom type is, -1 if NULL
for (int i = 3; i < nargs; i++) {
if (strcmp(args[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
map[i-2] = atoi(args[i]) - 1;
}
int n = atom->ntypes;
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++) {
setflag[i][j] = 1;
count++;
}
if (count == 0) error->all("Incorrect args for pair coefficients");
}
/* ---------------------------------------------------------------------- */
void PairReaxC::init_style( )
{
if (!atom->q_flag) error->all("Pair reax/c requires atom attribute q");
system->n = atom->nlocal;
system->N = atom->nlocal + atom->nghost;
system->bigN = static_cast<int> (atom->natoms);
system->wsize = comm->nprocs;
system->big_box.V = 0;
system->big_box.box_norms[0] = 0;
system->big_box.box_norms[1] = 0;
system->big_box.box_norms[2] = 0;
if (atom->tag_enable == 0)
error->all("Pair style reax/c requires atom IDs");
if (force->newton_pair == 0)
error->all("Pair style reax/c requires newton pair on");
// need a half neighbor list w/ Newton off
// built whenever re-neighboring occurs
int irequest = neighbor->request(this);
neighbor->requests[irequest]->newton = 2;
cutmax = MAX3(control->nonb_cut, control->hbond_cut, 2*control->bond_cut);
for( int i = 0; i < LIST_N; ++i )
lists[i].allocated = 0;
if (fix_reax == NULL) {
char **fixarg = new char*[3];
fixarg[0] = (char *) "REAXC";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "REAXC";
modify->add_fix(3,fixarg);
delete [] fixarg;
fix_reax = (FixReaxC *) modify->fix[modify->nfix-1];
}
}
/* ---------------------------------------------------------------------- */
double PairReaxC::init_one(int i, int j)
{
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::compute(int eflag, int vflag)
{
int k, oldN;
double evdwl,ecoul;
double t_start, t_end;
// communicate num_bonds once every reneighboring
// 2 num arrays stored by fix, grab ptr to them
if (neighbor->ago == 0) comm->forward_comm_fix(fix_reax);
int *num_bonds = fix_reax->num_bonds;
int *num_hbonds = fix_reax->num_hbonds;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = vflag_global = 0;
if (vflag_global) control->virial = 1;
else control->virial = 0;
system->n = atom->nlocal; // my atoms
oldN = system->N;
system->N = atom->nlocal + atom->nghost; // mine + ghosts
system->bigN = static_cast<int> (atom->natoms); // all atoms in the system
system->big_box.V = 0;
system->big_box.box_norms[0] = 0;
system->big_box.box_norms[1] = 0;
system->big_box.box_norms[2] = 0;
if( comm->me == 0 ) t_start = MPI_Wtime();
if( update->ntimestep == 0 ) {
control->vlist_cut = neighbor->cutneighmax;
// determine the local and total capacity
system->local_cap = MAX( (int)(system->n * SAFE_ZONE), MIN_CAP );
system->total_cap = MAX( (int)(system->N * SAFE_ZONE), MIN_CAP );
// initialize my data structures
PreAllocate_Space( system, control, workspace, world );
write_reax_atoms();
int num_nbrs = estimate_reax_lists();
if(!Make_List(system->total_cap, num_nbrs, TYP_FAR_NEIGHBOR,
lists+FAR_NBRS, world))
error->all("Pair reax/c problem in far neighbor list");
write_reax_lists();
Initialize( system, control, data, workspace, &lists, out_control,
mpi_data, world );
for( k = 0; k < system->N; ++k ) {
num_bonds[k] = system->my_atoms[k].num_bonds;
num_hbonds[k] = system->my_atoms[k].num_hbonds;
}
// locate the qeq/reax fix - for outputting log info
// if( comm->me == 0 ) {
// int qeq_id = modify->find_fix( "qeq/reax" );
// if (qeq_id < 0) fprintf(stderr, "WARNING: no qeq/reax fix applied\n");
// else fix_qeq = (FixQEqReax *) modify->fix[qeq_id];
// }
} else {
// fill in reax datastructures
write_reax_atoms();
// reset the bond list info for new atoms
for( k = oldN; k < system->N; ++k )
Set_End_Index( k, Start_Index( k, lists+BONDS ), lists+BONDS );
// check if I need to shrink/extend my data-structs
ReAllocate( system, control, data, workspace, &lists, mpi_data );
}
Reset( system, control, data, workspace, &lists, world );
workspace->realloc.num_far = write_reax_lists();
// timing for filling in the reax lists
if( comm->me == 0 ) {
t_end = MPI_Wtime();
data->timing.nbrs = t_end - t_start;
}
// forces
Compute_Forces(system,control,data,workspace,&lists,out_control,mpi_data);
read_reax_forces();
for( k = 0; k < system->N; ++k ) {
num_bonds[k] = system->my_atoms[k].num_bonds;
num_hbonds[k] = system->my_atoms[k].num_hbonds;
}
// energies and pressure
if (eflag_global) {
evdwl += data->my_en.e_bond;
evdwl += data->my_en.e_ov;
evdwl += data->my_en.e_un;
evdwl += data->my_en.e_lp;
evdwl += data->my_en.e_ang;
evdwl += data->my_en.e_pen;
evdwl += data->my_en.e_coa;
evdwl += data->my_en.e_hb;
evdwl += data->my_en.e_tor;
evdwl += data->my_en.e_con;
evdwl += data->my_en.e_vdW;
ecoul += data->my_en.e_ele;
ecoul += data->my_en.e_pol;
eng_vdwl += evdwl;
eng_coul += ecoul;
}
if (vflag_fdotr) virial_compute();
// #if defined(LOG_PERFORMANCE)
// if( comm->me == 0 && fix_qeq != NULL ) {
// data->timing.s_matvecs += fix_qeq->matvecs;
// data->timing.qEq += fix_qeq->qeq_time;
// }
// #endif
Output_Results( system, control, data, &lists, out_control, mpi_data );
++data->step;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::write_reax_atoms()
{
int *num_bonds = fix_reax->num_bonds;
int *num_hbonds = fix_reax->num_hbonds;
for( int i = 0; i < system->N; ++i ){
system->my_atoms[i].orig_id = atom->tag[i];
system->my_atoms[i].type = map[atom->type[i]];
system->my_atoms[i].x[0] = atom->x[i][0];
system->my_atoms[i].x[1] = atom->x[i][1];
system->my_atoms[i].x[2] = atom->x[i][2];
system->my_atoms[i].q = atom->q[i];
system->my_atoms[i].num_bonds = num_bonds[i];
system->my_atoms[i].num_hbonds = num_hbonds[i];
}
}
/* ---------------------------------------------------------------------- */
void PairReaxC::get_distance( rvec xj, rvec xi, double *d_sqr, rvec *dvec )
{
(*dvec)[0] = xj[0] - xi[0];
(*dvec)[1] = xj[1] - xi[1];
(*dvec)[2] = xj[2] - xi[2];
*d_sqr = SQR((*dvec)[0]) + SQR((*dvec)[1]) + SQR((*dvec)[2]);
}
/* ---------------------------------------------------------------------- */
void PairReaxC::set_far_nbr( far_neighbor_data *fdest,
int j, double d, rvec dvec )
{
fdest->nbr = j;
fdest->d = d;
rvec_Copy( fdest->dvec, dvec );
ivec_MakeZero( fdest->rel_box );
}
/* ---------------------------------------------------------------------- */
int PairReaxC::estimate_reax_lists()
{
int itr_i, itr_j, itr_g, i, j, g;
int nlocal, nghost, num_nbrs, num_marked;
int *ilist, *jlist, *numneigh, **firstneigh, *marked;
double d_sqr, g_d_sqr;
rvec dvec, g_dvec;
double *dist, **x;
reax_list *far_nbrs;
far_neighbor_data *far_list;
x = atom->x;
nlocal = atom->nlocal;
nghost = atom->nghost;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
far_nbrs = lists + FAR_NBRS;
far_list = far_nbrs->select.far_nbr_list;
num_nbrs = 0;
num_marked = 0;
marked = (int*) calloc( system->N, sizeof(int) );
dist = (double*) calloc( system->N, sizeof(double) );
for( itr_i = 0; itr_i < list->inum; ++itr_i ){
i = ilist[itr_i];
marked[i] = 1;
++num_marked;
jlist = firstneigh[i];
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
get_distance( x[j], x[i], &d_sqr, &dvec );
dist[j] = sqrt(d_sqr);
if( dist[j] <= control->nonb_cut )
++num_nbrs;
}
// compute the nbrs among ghost atoms
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
if( j >= nlocal && !marked[j] &&
dist[j] <= (control->vlist_cut - control->bond_cut) ){
marked[j] = 1;
++num_marked;
for( itr_g = 0; itr_g < numneigh[i]; ++itr_g ){
g = jlist[itr_g];
if( g >= nlocal && !marked[g] ){
get_distance( x[g], x[j], &g_d_sqr, &g_dvec );
//g_dvec[0] = x[g][0] - x[j][0];
//g_dvec[1] = x[g][1] - x[j][1];
//g_dvec[2] = x[g][2] - x[j][2];
//g_d_sqr = SQR(g_dvec[0]) + SQR(g_dvec[1]) + SQR(g_dvec[2]);
if( g_d_sqr <= SQR(control->bond_cut) )
++num_nbrs;
}
}
}
}
}
for( i = 0; i < system->N; ++i )
if( !marked[i] ) {
marked[i] = 1;
++num_marked;
for( j = i+1; j < system->N; ++j )
if( !marked[j] ) {
get_distance( x[j], x[i], &d_sqr, &dvec );
if( d_sqr <= SQR(control->bond_cut) )
++num_nbrs;
}
}
free( marked );
free( dist );
return static_cast<int> (MAX( num_nbrs*SAFE_ZONE, MIN_CAP*MIN_NBRS ));
}
/* ---------------------------------------------------------------------- */
int PairReaxC::write_reax_lists()
{
int itr_i, itr_j, itr_g, i, j, g;
int nlocal, nghost, num_nbrs;
int *ilist, *jlist, *numneigh, **firstneigh, *marked;
double d_sqr, g_d, g_d_sqr;
rvec dvec, g_dvec;
double *dist, **x;
reax_list *far_nbrs;
far_neighbor_data *far_list;
x = atom->x;
nlocal = atom->nlocal;
nghost = atom->nghost;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
far_nbrs = lists + FAR_NBRS;
far_list = far_nbrs->select.far_nbr_list;
num_nbrs = 0;
marked = (int*) calloc( system->N, sizeof(int) );
dist = (double*) calloc( system->N, sizeof(double) );
for( itr_i = 0; itr_i < list->inum; ++itr_i ){
i = ilist[itr_i];
marked[i] = 1;
jlist = firstneigh[i];
Set_Start_Index( i, num_nbrs, far_nbrs );
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
get_distance( x[j], x[i], &d_sqr, &dvec );
dist[j] = sqrt( d_sqr );
if( dist[j] <= control->nonb_cut ){
set_far_nbr( &far_list[num_nbrs], j, dist[j], dvec );
++num_nbrs;
}
}
Set_End_Index( i, num_nbrs, far_nbrs );
// compute the nbrs among ghost atoms
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
if( j >= nlocal && !marked[j] &&
dist[j] <= (control->vlist_cut - control->bond_cut) ){
marked[j] = 1;
Set_Start_Index( j, num_nbrs, far_nbrs );
for( itr_g = 0; itr_g < numneigh[i]; ++itr_g ){
g = jlist[itr_g];
if( g >= nlocal && !marked[g] ){
get_distance( x[g], x[j], &g_d_sqr, &g_dvec );
if( g_d_sqr <= SQR(control->bond_cut) ){
g_d = sqrt( g_d_sqr );
set_far_nbr( &far_list[num_nbrs], g, g_d, g_dvec );
++num_nbrs;
}
}
}
Set_End_Index( j, num_nbrs, far_nbrs );
}
}
}
for( i = 0; i < system->N; ++i )
if( !marked[i] ) {
marked[i] = 1;
Set_Start_Index( i, num_nbrs, far_nbrs );
for( j = i+1; j < system->N; ++j )
if( !marked[j] ) {
get_distance( x[j], x[i], &d_sqr, &dvec );
if( d_sqr <= SQR(control->bond_cut) ) {
set_far_nbr( &far_list[num_nbrs], j, sqrt(d_sqr), dvec );
++num_nbrs;
}
}
Set_End_Index( i, num_nbrs, far_nbrs );
}
free( marked );
free( dist );
return num_nbrs;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::read_reax_forces()
{
for( int i = 0; i < system->N; ++i ) {
system->my_atoms[i].f[0] = workspace->f[i][0];
system->my_atoms[i].f[1] = workspace->f[i][1];
system->my_atoms[i].f[2] = workspace->f[i][2];
atom->f[i][0] = -workspace->f[i][0];
atom->f[i][1] = -workspace->f[i][1];
atom->f[i][2] = -workspace->f[i][2];
}
}
/* ---------------------------------------------------------------------- */
void *PairReaxC::extract(char *str, int &dim)
{
dim = 1;
if (strcmp(str,"chi") == 0 && chi) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) chi[i] = system->reax_param.sbp[map[i]].chi;
else chi[i] = 0.0;
return (void *) chi;
}
if (strcmp(str,"eta") == 0 && eta) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) eta[i] = system->reax_param.sbp[map[i]].eta;
else eta[i] = 0.0;
return (void *) eta;
}
if (strcmp(str,"gamma") == 0 && gamma) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) gamma[i] = system->reax_param.sbp[map[i]].gamma;
else gamma[i] = 0.0;
return (void *) gamma;
}
return NULL;
}

View File

@ -0,0 +1,66 @@
/* ----------------------------------------------------------------------
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 PAIR_CLASS
PairStyle(reax/c,PairReaxC)
#else
#ifndef LMP_PAIR_REAXC_H
#define LMP_PAIR_REAXC_H
#include "pair.h"
#include "reaxc_types.h"
namespace LAMMPS_NS {
class PairReaxC : public Pair {
public:
PairReaxC(class LAMMPS *);
~PairReaxC();
void compute(int, int);
void settings(int, char **);
void coeff(int, char **);
void init_style();
double init_one(int, int);
void *extract(char *, int &);
private:
reax_system *system;
control_params *control;
simulation_data *data;
storage *workspace;
reax_list *lists;
output_controls *out_control;
mpi_datatypes *mpi_data;
double cutmax;
int *map;
class FixReaxC *fix_reax;
double *chi,*eta,*gamma;
void allocate();
void write_reax_atoms();
void get_distance(rvec, rvec, double *, rvec *);
void set_far_nbr(far_neighbor_data *, int, double, rvec);
int estimate_reax_lists();
int write_reax_lists();
void read_reax_forces();
};
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __ALLOCATE_H_
#define __ALLOCATE_H_
#include "reaxc_types.h"
int PreAllocate_Space( reax_system*, control_params*, storage*, MPI_Comm );
void reax_atom_Copy( reax_atom*, reax_atom* );
int Allocate_System( reax_system*, int, int, char* );
void DeAllocate_System( reax_system* );
int Allocate_Workspace( reax_system*, control_params*, storage*,
int, int, MPI_Comm, char* );
void DeAllocate_Workspace( control_params*, storage* );
void Allocate_Grid( reax_system*, MPI_Comm );
void Deallocate_Grid( grid* );
int Allocate_MPI_Buffers( mpi_datatypes*, int, neighbor_proc*, char* );
int Allocate_Matrix( sparse_matrix**, int, int, MPI_Comm );
int Allocate_HBond_List( int, int, int*, int*, reax_list* );
int Allocate_Bond_List( int, int*, reax_list* );
void ReAllocate( reax_system*, control_params*, simulation_data*, storage*,
reax_list**, mpi_datatypes* );
#endif

View File

@ -0,0 +1,312 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "basic_comm.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_basic_comm.h"
#include "reaxc_vector.h"
#endif
#if defined(PURE_REAX)
void real_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
real *buf = (real*) dummy;
real *out = (real*) out_buf->out_atoms;
for( i = 0; i < out_buf->cnt; ++i )
out[i] = buf[ out_buf->index[i] ];
}
void rvec_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
rvec *buf = (rvec*) dummy;
rvec *out = (rvec*)out_buf->out_atoms;
for( i = 0; i < out_buf->cnt; ++i )
memcpy( out[i], buf[ out_buf->index[i] ], sizeof(rvec) );
}
void rvec2_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
rvec2 *buf = (rvec2*) dummy;
rvec2 *out = (rvec2*) out_buf->out_atoms;
for( i = 0; i < out_buf->cnt; ++i )
memcpy( out[i], buf[ out_buf->index[i] ], sizeof(rvec2) );
}
void Dist( reax_system* system, mpi_datatypes *mpi_data,
void *buf, MPI_Datatype type, int scale, dist_packer pack )
{
int d;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
#if defined(DEBUG)
fprintf( stderr, "p%d dist: entered\n", system->my_rank );
#endif
comm = mpi_data->comm_mesh3D;
out_bufs = mpi_data->out_buffers;
for( d = 0; d < 3; ++d ) {
/* initiate recvs */
nbr1 = &(system->my_nbrs[2*d]);
if( nbr1->atoms_cnt )
MPI_Irecv( buf + nbr1->atoms_str*scale, nbr1->atoms_cnt, type,
nbr1->rank, 2*d+1,comm, &req1 );
nbr2 = &(system->my_nbrs[2*d+1]);
if( nbr2->atoms_cnt )
MPI_Irecv( buf + nbr2->atoms_str*scale, nbr2->atoms_cnt, type,
nbr2->rank, 2*d, comm, &req2 );
/* send both messages in dimension d */
if( out_bufs[2*d].cnt ) {
pack( buf, out_bufs + (2*d) );
MPI_Send( out_bufs[2*d].out_atoms, out_bufs[2*d].cnt, type,
nbr1->rank, 2*d, comm );
}
if( out_bufs[2*d+1].cnt ) {
pack( buf, out_bufs + (2*d+1) );
MPI_Send( out_bufs[2*d+1].out_atoms, out_bufs[2*d+1].cnt, type,
nbr2->rank, 2*d+1, comm );
}
if( nbr1->atoms_cnt ) MPI_Wait( &req1, &stat1 );
if( nbr2->atoms_cnt ) MPI_Wait( &req2, &stat2 );
}
#if defined(DEBUG)
fprintf( stderr, "p%d dist: done\n", system->my_rank );
#endif
}
void real_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
real *in = (real*) dummy_in;
real *buf = (real*) dummy_buf;
for( i = 0; i < out_buf->cnt; ++i )
buf[ out_buf->index[i] ] += in[i];
}
void rvec_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
rvec *in = (rvec*) dummy_in;
rvec *buf = (rvec*) dummy_buf;
for( i = 0; i < out_buf->cnt; ++i ) {
rvec_Add( buf[ out_buf->index[i] ], in[i] );
#if defined(DEBUG)
fprintf( stderr, "rvec_unpacker: cnt=%d i =%d index[i]=%d\n",
out_buf->cnt, i, out_buf->index[i] );
#endif
}
}
void rvec2_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
rvec2 *in = (rvec2*) dummy_in;
rvec2 *buf = (rvec2*) dummy_buf;
for( i = 0; i < out_buf->cnt; ++i ) {
buf[ out_buf->index[i] ][0] += in[i][0];
buf[ out_buf->index[i] ][1] += in[i][1];
}
}
void Coll( reax_system* system, mpi_datatypes *mpi_data,
void *buf, MPI_Datatype type, int scale, coll_unpacker unpack )
{
int d;
void *in1, *in2;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
#if defined(DEBUG)
fprintf( stderr, "p%d coll: entered\n", system->my_rank );
#endif
comm = mpi_data->comm_mesh3D;
in1 = mpi_data->in1_buffer;
in2 = mpi_data->in2_buffer;
out_bufs = mpi_data->out_buffers;
for( d = 2; d >= 0; --d ) {
/* initiate recvs */
nbr1 = &(system->my_nbrs[2*d]);
if( out_bufs[2*d].cnt )
MPI_Irecv(in1, out_bufs[2*d].cnt, type, nbr1->rank, 2*d+1, comm, &req1);
nbr2 = &(system->my_nbrs[2*d+1]);
if( out_bufs[2*d+1].cnt )
MPI_Irecv(in2, out_bufs[2*d+1].cnt, type, nbr2->rank, 2*d, comm, &req2);
/* send both messages in dimension d */
if( nbr1->atoms_cnt )
MPI_Send( buf + nbr1->atoms_str*scale, nbr1->atoms_cnt, type,
nbr1->rank, 2*d, comm );
if( nbr2->atoms_cnt )
MPI_Send( buf + nbr2->atoms_str*scale, nbr2->atoms_cnt, type,
nbr2->rank, 2*d+1, comm );
#if defined(DEBUG)
fprintf( stderr, "p%d coll[%d] nbr1: str=%d cnt=%d recv=%d\n",
system->my_rank, d, nbr1->atoms_str, nbr1->atoms_cnt,
out_bufs[2*d].cnt );
fprintf( stderr, "p%d coll[%d] nbr2: str=%d cnt=%d recv=%d\n",
system->my_rank, d, nbr2->atoms_str, nbr2->atoms_cnt,
out_bufs[2*d+1].cnt );
#endif
if( out_bufs[2*d].cnt ) {
MPI_Wait( &req1, &stat1 );
unpack( in1, buf, out_bufs + (2*d) );
}
if( out_bufs[2*d+1].cnt ) {
MPI_Wait( &req2, &stat2 );
unpack( in2, buf, out_bufs + (2*d+1) );
}
}
#if defined(DEBUG)
fprintf( stderr, "p%d coll: done\n", system->my_rank );
#endif
}
#endif /*PURE_REAX*/
/*****************************************************************************/
real Parallel_Norm( real *v, int n, MPI_Comm comm )
{
int i;
real my_sum, norm_sqr;
my_sum = 0;
for( i = 0; i < n; ++i )
my_sum += SQR( v[i] );
MPI_Allreduce( &my_sum, &norm_sqr, 1, MPI_DOUBLE, MPI_SUM, comm );
return sqrt( norm_sqr );
}
real Parallel_Dot( real *v1, real *v2, int n, MPI_Comm comm )
{
int i;
real my_dot, res;
my_dot = 0;
for( i = 0; i < n; ++i )
my_dot += v1[i] * v2[i];
MPI_Allreduce( &my_dot, &res, 1, MPI_DOUBLE, MPI_SUM, comm );
return res;
}
real Parallel_Vector_Acc( real *v, int n, MPI_Comm comm )
{
int i;
real my_acc, res;
my_acc = 0;
for( i = 0; i < n; ++i )
my_acc += v[i];
MPI_Allreduce( &my_acc, &res, 1, MPI_DOUBLE, MPI_SUM, comm );
return res;
}
/*****************************************************************************/
#if defined(TEST_FORCES)
void Coll_ids_at_Master( reax_system *system, storage *workspace,
mpi_datatypes *mpi_data )
{
int i;
int *id_list;
MPI_Gather( &system->n, 1, MPI_INT, workspace->rcounts, 1, MPI_INT,
MASTER_NODE, mpi_data->world );
if( system->my_rank == MASTER_NODE ){
workspace->displs[0] = 0;
for( i = 1; i < system->wsize; ++i )
workspace->displs[i] = workspace->displs[i-1] + workspace->rcounts[i-1];
}
id_list = (int*) malloc( system->n * sizeof(int) );
for( i = 0; i < system->n; ++i )
id_list[i] = system->my_atoms[i].orig_id;
MPI_Gatherv( id_list, system->n, MPI_INT,
workspace->id_all, workspace->rcounts, workspace->displs,
MPI_INT, MASTER_NODE, mpi_data->world );
free( id_list );
#if defined(DEBUG)
if( system->my_rank == MASTER_NODE ) {
for( i = 0 ; i < system->bigN; ++i )
fprintf( stderr, "id_all[%d]: %d\n", i, workspace->id_all[i] );
}
#endif
}
void Coll_rvecs_at_Master( reax_system *system, storage *workspace,
mpi_datatypes *mpi_data, rvec* v )
{
MPI_Gatherv( v, system->n, mpi_data->mpi_rvec,
workspace->f_all, workspace->rcounts, workspace->displs,
mpi_data->mpi_rvec, MASTER_NODE, mpi_data->world );
}
#endif

View File

@ -0,0 +1,47 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __BASIC_COMM_H_
#define __BASIC_COMM_H_
#include "reaxc_types.h"
void real_packer( void*, mpi_out_data* );
void rvec_packer( void*, mpi_out_data* );
void rvec2_packer( void*, mpi_out_data* );
void Dist(reax_system*, mpi_datatypes*, void*, MPI_Datatype, int, dist_packer);
void real_unpacker( void*, void*, mpi_out_data* );
void rvec_unpacker( void*, void*, mpi_out_data* );
void rvec2_unpacker( void*, void*, mpi_out_data* );
void Coll( reax_system*, mpi_datatypes*, void*, MPI_Datatype,
int, coll_unpacker );
real Parallel_Norm( real*, int, MPI_Comm );
real Parallel_Dot( real*, real*, int, MPI_Comm );
real Parallel_Vector_Acc( real*, int, MPI_Comm );
#if defined(TEST_FORCES)
void Coll_ids_at_Master( reax_system*, storage*, mpi_datatypes* );
void Coll_rvecs_at_Master( reax_system*, storage*, mpi_datatypes*, rvec* );
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __BOND_ORDERS_H_
#define __BOND_ORDERS_H_
#include "reaxc_types.h"
typedef struct{
real C1dbo, C2dbo, C3dbo;
real C1dbopi, C2dbopi, C3dbopi, C4dbopi;
real C1dbopi2, C2dbopi2, C3dbopi2, C4dbopi2;
real C1dDelta, C2dDelta, C3dDelta;
}dbond_coefficients;
#ifdef TEST_FORCES
void Get_dBO( reax_system*, reax_list**, int, int, real, rvec* );
void Get_dBOpinpi2( reax_system*, reax_list**,
int, int, real, real, rvec*, rvec* );
void Add_dBO( reax_system*, reax_list**, int, int, real, rvec* );
void Add_dBOpinpi2( reax_system*, reax_list**,
int, int, real, real, rvec*, rvec* );
void Add_dBO_to_Forces( reax_system*, reax_list**, int, int, real );
void Add_dBOpinpi2_to_Forces( reax_system*, reax_list**,
int, int, real, real );
void Add_dDelta( reax_system*, reax_list**, int, real, rvec* );
void Add_dDelta_to_Forces( reax_system *, reax_list**, int, real );
#endif
void Add_dBond_to_Forces( int, int, storage*, reax_list** );
void Add_dBond_to_Forces_NPT( int, int, simulation_data*,
storage*, reax_list** );
int BOp(storage*, reax_list*, real, int, int, far_neighbor_data*,
single_body_parameters*, single_body_parameters*, two_body_parameters*);
void BO( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
#endif

View File

@ -0,0 +1,148 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "bonds.h"
#include "bond_orders.h"
#include "list.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_bonds.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_tool_box.h"
#include "reaxc_vector.h"
#endif
void Bonds( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
output_controls *out_control )
{
int i, j, pj, natoms;
int start_i, end_i;
int type_i, type_j;
real ebond, pow_BOs_be2, exp_be12, CEbo;
real gp3, gp4, gp7, gp10, gp37;
real exphu, exphua1, exphub1, exphuov, hulpov, estriph;
real decobdbo, decobdboua, decobdboub;
single_body_parameters *sbp_i, *sbp_j;
two_body_parameters *twbp;
bond_order_data *bo_ij;
reax_list *bonds;
bonds = (*lists) + BONDS;
gp3 = system->reax_param.gp.l[3];
gp4 = system->reax_param.gp.l[4];
gp7 = system->reax_param.gp.l[7];
gp10 = system->reax_param.gp.l[10];
gp37 = (int) system->reax_param.gp.l[37];
natoms = system->n;
for( i = 0; i < natoms; ++i ) {
start_i = Start_Index(i, bonds);
end_i = End_Index(i, bonds);
for( pj = start_i; pj < end_i; ++pj ) {
j = bonds->select.bond_list[pj].nbr;
if( system->my_atoms[i].orig_id <= system->my_atoms[j].orig_id ) {
/* set the pointers */
type_i = system->my_atoms[i].type;
type_j = system->my_atoms[j].type;
sbp_i = &( system->reax_param.sbp[type_i] );
sbp_j = &( system->reax_param.sbp[type_j] );
twbp = &( system->reax_param.tbp[type_i][type_j] );
bo_ij = &( bonds->select.bond_list[pj].bo_data );
/* calculate the constants */
pow_BOs_be2 = pow( bo_ij->BO_s, twbp->p_be2 );
exp_be12 = exp( twbp->p_be1 * ( 1.0 - pow_BOs_be2 ) );
CEbo = -twbp->De_s * exp_be12 *
( 1.0 - twbp->p_be1 * twbp->p_be2 * pow_BOs_be2 );
/* calculate the Bond Energy */
data->my_en.e_bond += ebond =
-twbp->De_s * bo_ij->BO_s * exp_be12
-twbp->De_p * bo_ij->BO_pi
-twbp->De_pp * bo_ij->BO_pi2;
/* calculate derivatives of Bond Orders */
bo_ij->Cdbo += CEbo;
bo_ij->Cdbopi -= (CEbo + twbp->De_p);
bo_ij->Cdbopi2 -= (CEbo + twbp->De_pp);
#ifdef TEST_ENERGY
//fprintf( out_control->ebond, "%6d%6d%24.15e%24.15e%24.15e\n",
fprintf( out_control->ebond, "%6d%6d%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
bo_ij->BO, ebond, data->my_en.e_bond );
#endif
#ifdef TEST_FORCES
Add_dBO( system, lists, i, pj, CEbo, workspace->f_be );
Add_dBOpinpi2( system, lists, i, pj,
-(CEbo + twbp->De_p), -(CEbo + twbp->De_pp),
workspace->f_be, workspace->f_be );
#endif
/* Stabilisation terminal triple bond */
if( bo_ij->BO >= 1.00 ) {
if( gp37 == 2 ||
(sbp_i->mass == 12.0000 && sbp_j->mass == 15.9990) ||
(sbp_j->mass == 12.0000 && sbp_i->mass == 15.9990) ) {
exphu = exp( -gp7 * SQR(bo_ij->BO - 2.50) );
exphua1 = exp(-gp3 * (workspace->total_bond_order[i]-bo_ij->BO));
exphub1 = exp(-gp3 * (workspace->total_bond_order[j]-bo_ij->BO));
exphuov = exp(gp4 * (workspace->Delta[i] + workspace->Delta[j]));
hulpov = 1.0 / (1.0 + 25.0 * exphuov);
estriph = gp10 * exphu * hulpov * (exphua1 + exphub1);
data->my_en.e_bond += estriph;
decobdbo = gp10 * exphu * hulpov * (exphua1 + exphub1) *
( gp3 - 2.0 * gp7 * (bo_ij->BO-2.50) );
decobdboua = -gp10 * exphu * hulpov *
(gp3*exphua1 + 25.0*gp4*exphuov*hulpov*(exphua1+exphub1));
decobdboub = -gp10 * exphu * hulpov *
(gp3*exphub1 + 25.0*gp4*exphuov*hulpov*(exphua1+exphub1));
bo_ij->Cdbo += decobdbo;
workspace->CdDelta[i] += decobdboua;
workspace->CdDelta[j] += decobdboub;
#ifdef TEST_ENERGY
//fprintf( out_control->ebond,
// "%6d%6d%24.15e%24.15e%24.15e%24.15e\n",
// system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
// estriph, decobdbo, decobdboua, decobdboub );
#endif
#ifdef TEST_FORCES
Add_dBO( system, lists, i, pj, decobdbo, workspace->f_be );
Add_dDelta( system, lists, i, decobdboua, workspace->f_be );
Add_dDelta( system, lists, j, decobdboub, workspace->f_be );
#endif
}
}
}
}
}
}

View File

@ -0,0 +1,29 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __BONDS_H_
#define __BONDS_H_
#include "reaxc_types.h"
void Bonds( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
#endif

View File

@ -0,0 +1,395 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "control.h"
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_control.h"
#include "reaxc_tool_box.h"
#endif
char Read_Control_File( char *control_file, control_params* control,
output_controls *out_control )
{
FILE *fp;
char *s, **tmp;
int c,i,ival;
real val;
/* open control file */
if ( (fp = fopen( control_file, "r" ) ) == NULL ) {
fprintf( stderr, "error opening the control file! terminating...\n" );
MPI_Abort( MPI_COMM_WORLD, FILE_NOT_FOUND );
}
/* assign default values */
strcpy( control->sim_name, "simulate" );
control->ensemble = NVE;
control->nsteps = 0;
control->dt = 0.25;
control->nprocs = 1;
control->procs_by_dim[0] = 1;
control->procs_by_dim[1] = 1;
control->procs_by_dim[2] = 1;
control->geo_format = 1;
control->restart = 0;
out_control->restart_format = WRITE_BINARY;
out_control->restart_freq = 0;
control->reposition_atoms = 0;
control->restrict_bonds = 0;
control->remove_CoM_vel = 25;
out_control->debug_level = 0;
out_control->energy_update_freq = 0;
control->reneighbor = 1;
control->vlist_cut = control->nonb_cut;
control->bond_cut = 5.0;
control->bg_cut = 0.3;
control->thb_cut = 0.001;
control->hbond_cut = 0.0;
control->tabulate = 0;
control->qeq_freq = 1;
control->q_err = 1e-6;
control->refactor = 100;
control->droptol = 1e-2;;
control->T_init = 0.;
control->T_final = 300.;
control->Tau_T = 500.0;
control->T_mode = 0;
control->T_rate = 1.;
control->T_freq = 1.;
control->P[0] = control->P[1] = control->P[2] = 0.000101325;
control->Tau_P[0] = control->Tau_P[1] = control->Tau_P[2] = 500.0;
control->Tau_PT[0] = control->Tau_PT[1] = control->Tau_PT[2] = 500.0;
control->compressibility = 1.0;
control->press_mode = 0;
control->virial = 0;
out_control->write_steps = 0;
out_control->traj_compress = 0;
out_control->traj_method = REG_TRAJ;
strcpy( out_control->traj_title, "default_title" );
out_control->atom_info = 0;
out_control->bond_info = 0;
out_control->angle_info = 0;
control->molecular_analysis = 0;
control->dipole_anal = 0;
control->freq_dipole_anal = 0;
control->diffusion_coef = 0;
control->freq_diffusion_coef = 0;
control->restrict_type = 0;
/* memory allocations */
s = (char*) malloc(sizeof(char)*MAX_LINE);
tmp = (char**) malloc(sizeof(char*)*MAX_TOKENS);
for (i=0; i < MAX_TOKENS; i++)
tmp[i] = (char*) malloc(sizeof(char)*MAX_LINE);
/* read control parameters file */
while (!feof(fp)) {
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
//fprintf( stderr, "%s\n", s );
if( strcmp(tmp[0], "simulation_name") == 0 ) {
strcpy( control->sim_name, tmp[1] );
}
else if( strcmp(tmp[0], "ensemble_type") == 0 ) {
ival = atoi(tmp[1]);
control->ensemble = ival;
if( ival == iNPT || ival ==sNPT || ival == NPT )
control->virial = 1;
}
else if( strcmp(tmp[0], "nsteps") == 0 ) {
ival = atoi(tmp[1]);
control->nsteps = ival;
}
else if( strcmp(tmp[0], "dt") == 0) {
val = atof(tmp[1]);
control->dt = val * 1.e-3; // convert dt from fs to ps!
}
else if( strcmp(tmp[0], "proc_by_dim") == 0 ) {
ival = atoi(tmp[1]);
control->procs_by_dim[0] = ival;
ival = atoi(tmp[2]);
control->procs_by_dim[1] = ival;
ival = atoi(tmp[3]);
control->procs_by_dim[2] = ival;
control->nprocs = control->procs_by_dim[0]*control->procs_by_dim[1]*
control->procs_by_dim[2];
}
//else if( strcmp(tmp[0], "restart") == 0 ) {
// ival = atoi(tmp[1]);
// control->restart = ival;
//}
//else if( strcmp(tmp[0], "restart_from") == 0 ) {
// strcpy( control->restart_from, tmp[1] );
//}
else if( strcmp(tmp[0], "random_vel") == 0 ) {
ival = atoi(tmp[1]);
control->random_vel = ival;
}
else if( strcmp(tmp[0], "restart_format") == 0 ) {
ival = atoi(tmp[1]);
out_control->restart_format = ival;
}
else if( strcmp(tmp[0], "restart_freq") == 0 ) {
ival = atoi(tmp[1]);
out_control->restart_freq = ival;
}
else if( strcmp(tmp[0], "reposition_atoms") == 0 ) {
ival = atoi(tmp[1]);
control->reposition_atoms = ival;
}
else if( strcmp(tmp[0], "restrict_bonds") == 0 ) {
ival = atoi( tmp[1] );
control->restrict_bonds = ival;
}
else if( strcmp(tmp[0], "remove_CoM_vel") == 0 ) {
ival = atoi(tmp[1]);
control->remove_CoM_vel = ival;
}
else if( strcmp(tmp[0], "debug_level") == 0 ) {
ival = atoi(tmp[1]);
out_control->debug_level = ival;
}
else if( strcmp(tmp[0], "energy_update_freq") == 0 ) {
ival = atoi(tmp[1]);
out_control->energy_update_freq = ival;
}
else if( strcmp(tmp[0], "reneighbor") == 0 ) {
ival = atoi( tmp[1] );
control->reneighbor = ival;
}
else if( strcmp(tmp[0], "vlist_buffer") == 0 ) {
val = atof(tmp[1]);
control->vlist_cut= val + control->nonb_cut;
}
else if( strcmp(tmp[0], "nbrhood_cutoff") == 0 ) {
val = atof(tmp[1]);
control->bond_cut = val;
}
else if( strcmp(tmp[0], "bond_graph_cutoff") == 0 ) {
val = atof(tmp[1]);
control->bg_cut = val;
}
else if( strcmp(tmp[0], "thb_cutoff") == 0 ) {
val = atof(tmp[1]);
control->thb_cut = val;
}
else if( strcmp(tmp[0], "hbond_cutoff") == 0 ) {
val = atof( tmp[1] );
control->hbond_cut = val;
}
else if( strcmp(tmp[0], "ghost_cutoff") == 0 ) {
val = atof(tmp[1]);
control->user_ghost_cut = val;
}
else if( strcmp(tmp[0], "tabulate_long_range") == 0 ) {
ival = atoi( tmp[1] );
control->tabulate = ival;
}
else if( strcmp(tmp[0], "qeq_freq") == 0 ) {
ival = atoi( tmp[1] );
control->qeq_freq = ival;
}
else if( strcmp(tmp[0], "q_err") == 0 ) {
val = atof( tmp[1] );
control->q_err = val;
}
else if( strcmp(tmp[0], "ilu_refactor") == 0 ) {
ival = atoi( tmp[1] );
control->refactor = ival;
}
else if( strcmp(tmp[0], "ilu_droptol") == 0 ) {
val = atof( tmp[1] );
control->droptol = val;
}
else if( strcmp(tmp[0], "temp_init") == 0 ) {
val = atof(tmp[1]);
control->T_init = val;
if( control->T_init < 0.1 )
control->T_init = 0.1;
}
else if( strcmp(tmp[0], "temp_final") == 0 ) {
val = atof(tmp[1]);
control->T_final = val;
if( control->T_final < 0.1 )
control->T_final = 0.1;
}
else if( strcmp(tmp[0], "t_mass") == 0 ) {
val = atof(tmp[1]);
control->Tau_T = val * 1.e-3; // convert t_mass from fs to ps
}
else if( strcmp(tmp[0], "t_mode") == 0 ) {
ival = atoi(tmp[1]);
control->T_mode = ival;
}
else if( strcmp(tmp[0], "t_rate") == 0 ) {
val = atof(tmp[1]);
control->T_rate = val;
}
else if( strcmp(tmp[0], "t_freq") == 0 ) {
val = atof(tmp[1]);
control->T_freq = val;
}
else if( strcmp(tmp[0], "pressure") == 0 ) {
if( control->ensemble == iNPT ) {
control->P[0] = control->P[1] = control->P[2] = atof(tmp[1]);
}
else if( control->ensemble == sNPT ) {
control->P[0] = atof(tmp[1]);
control->P[1] = atof(tmp[2]);
control->P[2] = atof(tmp[3]);
}
}
else if( strcmp(tmp[0], "p_mass") == 0 ) {
// convert p_mass from fs to ps
if( control->ensemble == iNPT ) {
control->Tau_P[0] = control->Tau_P[1] = control->Tau_P[2] =
atof(tmp[1]) * 1.e-3;
}
else if( control->ensemble == sNPT ) {
control->Tau_P[0] = atof(tmp[1]) * 1.e-3;
control->Tau_P[1] = atof(tmp[2]) * 1.e-3;
control->Tau_P[2] = atof(tmp[3]) * 1.e-3;
}
}
else if( strcmp(tmp[0], "pt_mass") == 0 ) {
val = atof(tmp[1]);
control->Tau_PT[0] = control->Tau_PT[1] = control->Tau_PT[2] =
val * 1.e-3; // convert pt_mass from fs to ps
}
else if( strcmp(tmp[0], "compress") == 0 ) {
val = atof(tmp[1]);
control->compressibility = val;
}
else if( strcmp(tmp[0], "press_mode") == 0 ) {
ival = atoi(tmp[1]);
control->press_mode = ival;
}
else if( strcmp(tmp[0], "geo_format") == 0 ) {
ival = atoi( tmp[1] );
control->geo_format = ival;
}
else if( strcmp(tmp[0], "write_freq") == 0 ) {
ival = atoi(tmp[1]);
out_control->write_steps = ival;
}
else if( strcmp(tmp[0], "traj_compress") == 0 ) {
ival = atoi(tmp[1]);
out_control->traj_compress = ival;
}
else if( strcmp(tmp[0], "traj_method") == 0 ) {
ival = atoi(tmp[1]);
out_control->traj_method = ival;
}
else if( strcmp(tmp[0], "traj_title") == 0 ) {
strcpy( out_control->traj_title, tmp[1] );
}
else if( strcmp(tmp[0], "atom_info") == 0 ) {
ival = atoi(tmp[1]);
out_control->atom_info += ival * 4;
}
else if( strcmp(tmp[0], "atom_velocities") == 0 ) {
ival = atoi(tmp[1]);
out_control->atom_info += ival * 2;
}
else if( strcmp(tmp[0], "atom_forces") == 0 ) {
ival = atoi(tmp[1]);
out_control->atom_info += ival * 1;
}
else if( strcmp(tmp[0], "bond_info") == 0 ) {
ival = atoi(tmp[1]);
out_control->bond_info = ival;
}
else if( strcmp(tmp[0], "angle_info") == 0 ) {
ival = atoi(tmp[1]);
out_control->angle_info = ival;
}
else if( strcmp(tmp[0], "molecular_analysis") == 0 ) {
ival = atoi(tmp[1]);
control->molecular_analysis = ival;
}
else if( strcmp(tmp[0], "ignore") == 0 ) {
control->num_ignored = atoi(tmp[1]);
for( i = 0; i < control->num_ignored; ++i )
control->ignore[atoi(tmp[i+2])] = 1;
}
else if( strcmp(tmp[0], "dipole_anal") == 0 ) {
ival = atoi(tmp[1]);
control->dipole_anal = ival;
}
else if( strcmp(tmp[0], "freq_dipole_anal") == 0 ) {
ival = atoi(tmp[1]);
control->freq_dipole_anal = ival;
}
else if( strcmp(tmp[0], "diffusion_coef") == 0 ) {
ival = atoi(tmp[1]);
control->diffusion_coef = ival;
}
else if( strcmp(tmp[0], "freq_diffusion_coef") == 0 ) {
ival = atoi(tmp[1]);
control->freq_diffusion_coef = ival;
}
else if( strcmp(tmp[0], "restrict_type") == 0 ) {
ival = atoi(tmp[1]);
control->restrict_type = ival;
}
else {
fprintf( stderr, "WARNING: unknown parameter %s\n", tmp[0] );
MPI_Abort( MPI_COMM_WORLD, 15 );
}
}
/* determine target T */
if( control->T_mode == 0 )
control->T = control->T_final;
else control->T = control->T_init;
/* free memory allocations at the top */
for( i = 0; i < MAX_TOKENS; i++ )
free( tmp[i] );
free( tmp );
free( s );
// fprintf( stderr,"%d %d %10.5f %d %10.5f %10.5f\n",
// control->ensemble, control->nsteps, control->dt,
// control->tabulate, control->T, control->P );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "control file read\n" );
#endif
return SUCCESS;
}

View File

@ -0,0 +1,29 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __CONTROL_H_
#define __CONTROL_H_
#include "reaxc_types.h"
char Read_Control_File( char*, control_params*, output_controls* );
#endif

141
src/USER-REAXC/reaxc_defs.h Normal file
View File

@ -0,0 +1,141 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef REAX_DEFS_H
#define REAX_DEFS_H
#if defined(__IBMC__)
#define inline __inline__
#endif /*IBMC*/
#define SUCCESS 1
#define FAILURE 0
#define TRUE 1
#define FALSE 0
#define SQR(x) ((x)*(x))
#define CUBE(x) ((x)*(x)*(x))
#define DEG2RAD(a) ((a)*constPI/180.0)
#define RAD2DEG(a) ((a)*180.0/constPI)
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX3(x,y,z) MAX( MAX(x,y), z)
#define constPI 3.14159265
#define C_ele 332.06371
//#define K_B 503.398008 // kcal/mol/K
#define K_B 0.831687 // amu A^2 / ps^2 / K
#define F_CONV 1e6 / 48.88821291 / 48.88821291 // --> amu A / ps^2
#define E_CONV 0.002391 // amu A^2 / ps^2 --> kcal/mol
#define EV_to_KCALpMOL 14.400000 // ElectronVolt --> KCAL per MOLe
#define KCALpMOL_to_EV 23.02 // 23.060549 //KCAL per MOLe --> ElectronVolt
#define ECxA_to_DEBYE 4.803204 // elem. charge * Ang -> debye
#define CAL_to_JOULES 4.184000 // CALories --> JOULES
#define JOULES_to_CAL 1/4.184000 // JOULES --> CALories
#define AMU_to_GRAM 1.6605e-24
#define ANG_to_CM 1e-8
#define AVOGNR 6.0221367e23
#define P_CONV 1e-24 * AVOGNR * JOULES_to_CAL
#define MAX_STR 1024
#define MAX_LINE 1024
#define MAX_TOKENS 1024
#define MAX_TOKEN_LEN 1024
#define MAX_ATOM_ID 100000
#define MAX_RESTRICT 15
#define MAX_MOLECULE_SIZE 20
#define MAX_ATOM_TYPES 25
#define NUM_INTRS 10
#define ALMOST_ZERO 1e-10
#define NEG_INF -1e10
#define NO_BOND 1e-3 // 0.001
#define HB_THRESHOLD 1e-2 // 0.01
#define MIN_CAP 50
#define MIN_NBRS 100
#define MIN_HENTRIES 100
#define MAX_BONDS 30
#define MIN_BONDS 15
#define MIN_HBONDS 25
#define MIN_3BODIES 1000
#define MIN_GCELL_POPL 50
#define MIN_SEND 100
#define SAFE_ZONE 1.2
#define SAFER_ZONE 1.4
#define DANGER_ZONE 0.90
#define LOOSE_ZONE 0.75
#define MAX_3BODY_PARAM 5
#define MAX_4BODY_PARAM 5
#define MAX_dV 1.01
#define MIN_dV 0.99
#define MAX_dT 4.00
#define MIN_dT 0.00
#define MASTER_NODE 0
#define MAX_NBRS 6 //27
#define MYSELF 13 // encoding of relative coordinate (0,0,0)
#define MAX_ITR 10
#define RESTART 30
/******************* ENUMERATIONS *************************/
enum geo_formats { CUSTOM, PDB, ASCII_RESTART, BINARY_RESTART, GF_N };
enum restart_formats { WRITE_ASCII, WRITE_BINARY, RF_N };
enum ensembles { NVE, bNVT, nhNVT, sNPT, iNPT, NPT, ens_N };
enum lists { BONDS, OLD_BONDS, THREE_BODIES,
HBONDS, FAR_NBRS, DBOS, DDELTAS, LIST_N };
enum interactions { TYP_VOID, TYP_BOND, TYP_THREE_BODY,
TYP_HBOND, TYP_FAR_NEIGHBOR, TYP_DBO, TYP_DDELTA, TYP_N };
enum message_tags { INIT, UPDATE, BNDRY, UPDATE_BNDRY,
EXC_VEC1, EXC_VEC2, DIST_RVEC2, COLL_RVEC2,
DIST_RVECS, COLL_RVECS, INIT_DESCS, ATOM_LINES,
BOND_LINES, ANGLE_LINES, RESTART_ATOMS, TAGS_N };
enum errors { FILE_NOT_FOUND = -10, UNKNOWN_ATOM_TYPE = -11,
CANNOT_OPEN_FILE = -12, CANNOT_INITIALIZE = -13,
INSUFFICIENT_MEMORY = -14, UNKNOWN_OPTION = -15,
INVALID_INPUT = -16, INVALID_GEO = -17 };
enum exchanges { NONE, NEAR_EXCH, FULL_EXCH };
enum gcell_types { NO_NBRS=0, NEAR_ONLY=1, HBOND_ONLY=2, FAR_ONLY=4,
NEAR_HBOND=3, NEAR_FAR=5, HBOND_FAR=6, FULL_NBRS=7,
NATIVE=8 };
enum atoms { C_ATOM = 0, H_ATOM = 1, O_ATOM = 2, N_ATOM = 3,
S_ATOM = 4, SI_ATOM = 5, GE_ATOM = 6, X_ATOM = 7 };
enum traj_methods { REG_TRAJ, MPI_TRAJ, TF_N };
enum molecules { UNKNOWN, WATER };
#endif

View File

@ -0,0 +1,715 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "ffield.h"
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_ffield.h"
#include "reaxc_tool_box.h"
#endif
char Read_Force_Field( char *ffield_file, reax_interaction *reax,
control_params *control )
{
FILE *fp;
char *s;
char **tmp;
char ****tor_flag;
int c, i, j, k, l, m, n, o, p, cnt;
real val;
MPI_Comm comm;
comm = MPI_COMM_WORLD;
/* open force field file */
if ( (fp = fopen( ffield_file, "r" ) ) == NULL ) {
fprintf( stderr, "error opening the force filed file! terminating...\n" );
MPI_Abort( comm, FILE_NOT_FOUND );
}
s = (char*) malloc(sizeof(char)*MAX_LINE);
tmp = (char**) malloc(sizeof(char*)*MAX_TOKENS);
for (i=0; i < MAX_TOKENS; i++)
tmp[i] = (char*) malloc(sizeof(char)*MAX_TOKEN_LEN);
/* reading first header comment */
fgets( s, MAX_LINE, fp );
/* line 2 is number of global parameters */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
/* reading the number of global parameters */
n = atoi(tmp[0]);
if (n < 1) {
fprintf( stderr, "WARNING: number of globals in ffield file is 0!\n" );
fclose(fp);
return 1;
}
reax->gp.n_global = n;
reax->gp.l = (real*) malloc(sizeof(real)*n);
/* see reax_types.h for mapping between l[i] and the lambdas used in ff */
for (i=0; i < n; i++) {
fgets(s,MAX_LINE,fp);
c = Tokenize(s,&tmp);
val = (real) atof(tmp[0]);
reax->gp.l[i] = val;
}
control->bo_cut = 0.01 * reax->gp.l[29];
control->nonb_low = reax->gp.l[11];
control->nonb_cut = reax->gp.l[12];
/* next line is number of atom types and some comments */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
reax->num_atom_types = atoi(tmp[0]);
/* 3 lines of comments */
fgets(s,MAX_LINE,fp);
fgets(s,MAX_LINE,fp);
fgets(s,MAX_LINE,fp);
/* Allocating structures in reax_interaction */
reax->sbp = (single_body_parameters*)
scalloc( reax->num_atom_types, sizeof(single_body_parameters), "sbp",
comm );
reax->tbp = (two_body_parameters**)
scalloc( reax->num_atom_types, sizeof(two_body_parameters*), "tbp", comm );
reax->thbp= (three_body_header***)
scalloc( reax->num_atom_types, sizeof(three_body_header**), "thbp", comm );
reax->hbp = (hbond_parameters***)
scalloc( reax->num_atom_types, sizeof(hbond_parameters**), "hbp", comm );
reax->fbp = (four_body_header****)
scalloc( reax->num_atom_types, sizeof(four_body_header***), "fbp", comm );
tor_flag = (char****)
scalloc( reax->num_atom_types, sizeof(char***), "tor_flag", comm );
for( i = 0; i < reax->num_atom_types; i++ ) {
reax->tbp[i] = (two_body_parameters*)
scalloc( reax->num_atom_types, sizeof(two_body_parameters), "tbp[i]",
comm );
reax->thbp[i]= (three_body_header**)
scalloc( reax->num_atom_types, sizeof(three_body_header*), "thbp[i]",
comm );
reax->hbp[i] = (hbond_parameters**)
scalloc( reax->num_atom_types, sizeof(hbond_parameters*), "hbp[i]",
comm );
reax->fbp[i] = (four_body_header***)
scalloc( reax->num_atom_types, sizeof(four_body_header**), "fbp[i]",
comm );
tor_flag[i] = (char***)
scalloc( reax->num_atom_types, sizeof(char**), "tor_flag[i]", comm );
for( j = 0; j < reax->num_atom_types; j++ ) {
reax->thbp[i][j]= (three_body_header*)
scalloc( reax->num_atom_types, sizeof(three_body_header), "thbp[i,j]",
comm );
reax->hbp[i][j] = (hbond_parameters*)
scalloc( reax->num_atom_types, sizeof(hbond_parameters), "hbp[i,j]",
comm );
reax->fbp[i][j] = (four_body_header**)
scalloc( reax->num_atom_types, sizeof(four_body_header*), "fbp[i,j]",
comm );
tor_flag[i][j] = (char**)
scalloc( reax->num_atom_types, sizeof(char*), "tor_flag[i,j]", comm );
for (k=0; k < reax->num_atom_types; k++) {
reax->fbp[i][j][k] = (four_body_header*)
scalloc( reax->num_atom_types, sizeof(four_body_header), "fbp[i,j,k]",
comm );
tor_flag[i][j][k] = (char*)
scalloc( reax->num_atom_types, sizeof(char), "tor_flag[i,j,k]",
comm );
}
}
}
// vdWaals type: 1: Shielded Morse, no inner-wall
// 2: inner wall, no shielding
// 3: inner wall+shielding
reax->gp.vdw_type = 0;
/* reading single atom parameters */
/* there are 4 lines of each single atom parameters in ff files. these
parameters later determine some of the pair and triplet parameters using
combination rules. */
for( i = 0; i < reax->num_atom_types; i++ ) {
/* line one */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
for( j = 0; j < (int)(strlen(tmp[0])); ++j )
reax->sbp[i].name[j] = toupper( tmp[0][j] );
val = atof(tmp[1]); reax->sbp[i].r_s = val;
val = atof(tmp[2]); reax->sbp[i].valency = val;
val = atof(tmp[3]); reax->sbp[i].mass = val;
val = atof(tmp[4]); reax->sbp[i].r_vdw = val;
val = atof(tmp[5]); reax->sbp[i].epsilon = val;
val = atof(tmp[6]); reax->sbp[i].gamma = val;
val = atof(tmp[7]); reax->sbp[i].r_pi = val;
val = atof(tmp[8]); reax->sbp[i].valency_e = val;
reax->sbp[i].nlp_opt = 0.5 * (reax->sbp[i].valency_e-reax->sbp[i].valency);
/* line two */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
val = atof(tmp[0]); reax->sbp[i].alpha = val;
val = atof(tmp[1]); reax->sbp[i].gamma_w = val;
val = atof(tmp[2]); reax->sbp[i].valency_boc= val;
val = atof(tmp[3]); reax->sbp[i].p_ovun5 = val;
val = atof(tmp[4]);
val = atof(tmp[5]); reax->sbp[i].chi = val;
val = atof(tmp[6]); reax->sbp[i].eta = 2.0 * val;
val = atof(tmp[7]); reax->sbp[i].p_hbond = (int) val;
/* line 3 */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
val = atof(tmp[0]); reax->sbp[i].r_pi_pi = val;
val = atof(tmp[1]); reax->sbp[i].p_lp2 = val;
val = atof(tmp[2]);
val = atof(tmp[3]); reax->sbp[i].b_o_131 = val;
val = atof(tmp[4]); reax->sbp[i].b_o_132 = val;
val = atof(tmp[5]); reax->sbp[i].b_o_133 = val;
val = atof(tmp[6]);
val = atof(tmp[7]);
/* line 4 */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
val = atof(tmp[0]); reax->sbp[i].p_ovun2 = val;
val = atof(tmp[1]); reax->sbp[i].p_val3 = val;
val = atof(tmp[2]);
val = atof(tmp[3]); reax->sbp[i].valency_val= val;
val = atof(tmp[4]); reax->sbp[i].p_val5 = val;
val = atof(tmp[5]); reax->sbp[i].rcore2 = val;
val = atof(tmp[6]); reax->sbp[i].ecore2 = val;
val = atof(tmp[7]); reax->sbp[i].acore2 = val;
if( reax->sbp[i].rcore2>0.01 && reax->sbp[i].acore2>0.01 ){ // Inner-wall
if( reax->sbp[i].gamma_w>0.5 ){ // Shielding vdWaals
if( reax->gp.vdw_type != 0 && reax->gp.vdw_type != 3 )
fprintf( stderr, "Warning: inconsistent vdWaals-parameters\n" \
"Force field parameters for element %s\n" \
"indicate inner wall+shielding, but earlier\n" \
"atoms indicate different vdWaals-method.\n" \
"This may cause division-by-zero errors.\n" \
"Keeping vdWaals-setting for earlier atoms.\n",
reax->sbp[i].name );
else{
reax->gp.vdw_type = 3;
#if defined(DEBUG)
fprintf( stderr, "vdWaals type for element %s: Shielding+inner-wall",
reax->sbp[i].name );
#endif
}
}
else { // No shielding vdWaals parameters present
if( reax->gp.vdw_type != 0 && reax->gp.vdw_type != 2 )
fprintf( stderr, "Warning: inconsistent vdWaals-parameters\n" \
"Force field parameters for element %s\n" \
"indicate inner wall without shielding, but earlier\n" \
"atoms indicate different vdWaals-method.\n" \
"This may cause division-by-zero errors.\n" \
"Keeping vdWaals-setting for earlier atoms.\n",
reax->sbp[i].name );
else{
reax->gp.vdw_type = 2;
#if defined(DEBUG)
fprintf( stderr,"vdWaals type for element%s: No Shielding,inner-wall",
reax->sbp[i].name );
#endif
}
}
}
else{ // No Inner wall parameters present
if( reax->sbp[i].gamma_w>0.5 ){ // Shielding vdWaals
if( reax->gp.vdw_type != 0 && reax->gp.vdw_type != 1 )
fprintf( stderr, "Warning: inconsistent vdWaals-parameters\n" \
"Force field parameters for element %s\n" \
"indicate shielding without inner wall, but earlier\n" \
"atoms indicate different vdWaals-method.\n" \
"This may cause division-by-zero errors.\n" \
"Keeping vdWaals-setting for earlier atoms.\n",
reax->sbp[i].name );
else{
reax->gp.vdw_type = 1;
#if defined(DEBUG)
fprintf( stderr,"vdWaals type for element%s: Shielding,no inner-wall",
reax->sbp[i].name );
#endif
}
}
else{
fprintf( stderr, "Error: inconsistent vdWaals-parameters\n"\
"No shielding or inner-wall set for element %s\n",
reax->sbp[i].name );
MPI_Abort( comm, INVALID_INPUT );
}
}
}
#if defined(DEBUG)
fprintf( stderr, "vdWaals type: %d\n", reax->gp.vdw_type );
#endif
/* Equate vval3 to valf for first-row elements (25/10/2004) */
for( i = 0; i < reax->num_atom_types; i++ )
if( reax->sbp[i].mass < 21 &&
reax->sbp[i].valency_val != reax->sbp[i].valency_boc ){
fprintf( stderr, "Warning: changed valency_val to valency_boc for %s\n",
reax->sbp[i].name );
reax->sbp[i].valency_val = reax->sbp[i].valency_boc;
}
/* next line is number of two body combination and some comments */
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
l = atoi(tmp[0]);
/* a line of comments */
fgets(s,MAX_LINE,fp);
for (i=0; i < l; i++) {
/* line 1 */
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
j = atoi(tmp[0]) - 1;
k = atoi(tmp[1]) - 1;
if (j < reax->num_atom_types && k < reax->num_atom_types) {
val = atof(tmp[2]); reax->tbp[j][k].De_s = val;
reax->tbp[k][j].De_s = val;
val = atof(tmp[3]); reax->tbp[j][k].De_p = val;
reax->tbp[k][j].De_p = val;
val = atof(tmp[4]); reax->tbp[j][k].De_pp = val;
reax->tbp[k][j].De_pp = val;
val = atof(tmp[5]); reax->tbp[j][k].p_be1 = val;
reax->tbp[k][j].p_be1 = val;
val = atof(tmp[6]); reax->tbp[j][k].p_bo5 = val;
reax->tbp[k][j].p_bo5 = val;
val = atof(tmp[7]); reax->tbp[j][k].v13cor = val;
reax->tbp[k][j].v13cor = val;
val = atof(tmp[8]); reax->tbp[j][k].p_bo6 = val;
reax->tbp[k][j].p_bo6 = val;
val = atof(tmp[9]); reax->tbp[j][k].p_ovun1 = val;
reax->tbp[k][j].p_ovun1 = val;
/* line 2 */
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
val = atof(tmp[0]); reax->tbp[j][k].p_be2 = val;
reax->tbp[k][j].p_be2 = val;
val = atof(tmp[1]); reax->tbp[j][k].p_bo3 = val;
reax->tbp[k][j].p_bo3 = val;
val = atof(tmp[2]); reax->tbp[j][k].p_bo4 = val;
reax->tbp[k][j].p_bo4 = val;
val = atof(tmp[3]);
val = atof(tmp[4]); reax->tbp[j][k].p_bo1 = val;
reax->tbp[k][j].p_bo1 = val;
val = atof(tmp[5]); reax->tbp[j][k].p_bo2 = val;
reax->tbp[k][j].p_bo2 = val;
val = atof(tmp[6]); reax->tbp[j][k].ovc = val;
reax->tbp[k][j].ovc = val;
val = atof(tmp[7]);
}
}
/* calculating combination rules and filling up remaining fields. */
for (i=0; i < reax->num_atom_types; i++)
for (j=i; j < reax->num_atom_types; j++) {
reax->tbp[i][j].r_s = 0.5 *
(reax->sbp[i].r_s + reax->sbp[j].r_s);
reax->tbp[j][i].r_s = 0.5 *
(reax->sbp[j].r_s + reax->sbp[i].r_s);
reax->tbp[i][j].r_p = 0.5 *
(reax->sbp[i].r_pi + reax->sbp[j].r_pi);
reax->tbp[j][i].r_p = 0.5 *
(reax->sbp[j].r_pi + reax->sbp[i].r_pi);
reax->tbp[i][j].r_pp = 0.5 *
(reax->sbp[i].r_pi_pi + reax->sbp[j].r_pi_pi);
reax->tbp[j][i].r_pp = 0.5 *
(reax->sbp[j].r_pi_pi + reax->sbp[i].r_pi_pi);
reax->tbp[i][j].p_boc3 =
sqrt(reax->sbp[i].b_o_132 *
reax->sbp[j].b_o_132);
reax->tbp[j][i].p_boc3 =
sqrt(reax->sbp[j].b_o_132 *
reax->sbp[i].b_o_132);
reax->tbp[i][j].p_boc4 =
sqrt(reax->sbp[i].b_o_131 *
reax->sbp[j].b_o_131);
reax->tbp[j][i].p_boc4 =
sqrt(reax->sbp[j].b_o_131 *
reax->sbp[i].b_o_131);
reax->tbp[i][j].p_boc5 =
sqrt(reax->sbp[i].b_o_133 *
reax->sbp[j].b_o_133);
reax->tbp[j][i].p_boc5 =
sqrt(reax->sbp[j].b_o_133 *
reax->sbp[i].b_o_133);
reax->tbp[i][j].D =
sqrt(reax->sbp[i].epsilon *
reax->sbp[j].epsilon);
reax->tbp[j][i].D =
sqrt(reax->sbp[j].epsilon *
reax->sbp[i].epsilon);
reax->tbp[i][j].alpha =
sqrt(reax->sbp[i].alpha *
reax->sbp[j].alpha);
reax->tbp[j][i].alpha =
sqrt(reax->sbp[j].alpha *
reax->sbp[i].alpha);
reax->tbp[i][j].r_vdW =
2.0 * sqrt(reax->sbp[i].r_vdw * reax->sbp[j].r_vdw);
reax->tbp[j][i].r_vdW =
2.0 * sqrt(reax->sbp[j].r_vdw * reax->sbp[i].r_vdw);
reax->tbp[i][j].gamma_w =
sqrt(reax->sbp[i].gamma_w *
reax->sbp[j].gamma_w);
reax->tbp[j][i].gamma_w =
sqrt(reax->sbp[j].gamma_w *
reax->sbp[i].gamma_w);
reax->tbp[i][j].gamma =
pow(reax->sbp[i].gamma *
reax->sbp[j].gamma,-1.5);
reax->tbp[j][i].gamma =
pow(reax->sbp[j].gamma *
reax->sbp[i].gamma,-1.5);
// additions for additional vdWaals interaction types - inner core
reax->tbp[i][j].rcore = reax->tbp[j][i].rcore =
sqrt( reax->sbp[i].rcore2 * reax->sbp[j].rcore2 );
reax->tbp[i][j].ecore = reax->tbp[j][i].ecore =
sqrt( reax->sbp[i].ecore2 * reax->sbp[j].ecore2 );
reax->tbp[i][j].acore = reax->tbp[j][i].acore =
sqrt( reax->sbp[i].acore2 * reax->sbp[j].acore2 );
}
/* next line is number of two body offdiagonal combinations and comments */
/* these are two body offdiagonal terms that are different from the
combination rules defined above */
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
l = atoi(tmp[0]);
for (i=0; i < l; i++) {
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
j = atoi(tmp[0]) - 1;
k = atoi(tmp[1]) - 1;
if (j < reax->num_atom_types && k < reax->num_atom_types) {
val = atof(tmp[2]);
if (val > 0.0) {
reax->tbp[j][k].D = val;
reax->tbp[k][j].D = val;
}
val = atof(tmp[3]);
if (val > 0.0) {
reax->tbp[j][k].r_vdW = 2 * val;
reax->tbp[k][j].r_vdW = 2 * val;
}
val = atof(tmp[4]);
if (val > 0.0) {
reax->tbp[j][k].alpha = val;
reax->tbp[k][j].alpha = val;
}
val = atof(tmp[5]);
if (val > 0.0) {
reax->tbp[j][k].r_s = val;
reax->tbp[k][j].r_s = val;
}
val = atof(tmp[6]);
if (val > 0.0) {
reax->tbp[j][k].r_p = val;
reax->tbp[k][j].r_p = val;
}
val = atof(tmp[7]);
if (val > 0.0) {
reax->tbp[j][k].r_pp = val;
reax->tbp[k][j].r_pp = val;
}
}
}
/* 3-body parameters -
supports multi-well potentials (upto MAX_3BODY_PARAM in mytypes.h) */
/* clear entries first */
for( i = 0; i < reax->num_atom_types; ++i )
for( j = 0; j < reax->num_atom_types; ++j )
for( k = 0; k < reax->num_atom_types; ++k )
reax->thbp[i][j][k].cnt = 0;
/* next line is number of 3-body params and some comments */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
l = atoi( tmp[0] );
for( i = 0; i < l; i++ ) {
fgets(s,MAX_LINE,fp);
c=Tokenize(s,&tmp);
j = atoi(tmp[0]) - 1;
k = atoi(tmp[1]) - 1;
m = atoi(tmp[2]) - 1;
if (j < reax->num_atom_types && k < reax->num_atom_types &&
m < reax->num_atom_types) {
cnt = reax->thbp[j][k][m].cnt;
reax->thbp[j][k][m].cnt++;
reax->thbp[m][k][j].cnt++;
val = atof(tmp[3]);
reax->thbp[j][k][m].prm[cnt].theta_00 = val;
reax->thbp[m][k][j].prm[cnt].theta_00 = val;
val = atof(tmp[4]);
reax->thbp[j][k][m].prm[cnt].p_val1 = val;
reax->thbp[m][k][j].prm[cnt].p_val1 = val;
val = atof(tmp[5]);
reax->thbp[j][k][m].prm[cnt].p_val2 = val;
reax->thbp[m][k][j].prm[cnt].p_val2 = val;
val = atof(tmp[6]);
reax->thbp[j][k][m].prm[cnt].p_coa1 = val;
reax->thbp[m][k][j].prm[cnt].p_coa1 = val;
val = atof(tmp[7]);
reax->thbp[j][k][m].prm[cnt].p_val7 = val;
reax->thbp[m][k][j].prm[cnt].p_val7 = val;
val = atof(tmp[8]);
reax->thbp[j][k][m].prm[cnt].p_pen1 = val;
reax->thbp[m][k][j].prm[cnt].p_pen1 = val;
val = atof(tmp[9]);
reax->thbp[j][k][m].prm[cnt].p_val4 = val;
reax->thbp[m][k][j].prm[cnt].p_val4 = val;
}
}
/* 4-body parameters are entered in compact form. i.e. 0-X-Y-0
correspond to any type of pair of atoms in 1 and 4
position. However, explicit X-Y-Z-W takes precedence over the
default description.
supports multi-well potentials (upto MAX_4BODY_PARAM in mytypes.h)
IMPORTANT: for now, directions on how to read multi-entries from ffield
is not clear */
/* clear all entries first */
for( i = 0; i < reax->num_atom_types; ++i )
for( j = 0; j < reax->num_atom_types; ++j )
for( k = 0; k < reax->num_atom_types; ++k )
for( m = 0; m < reax->num_atom_types; ++m ) {
reax->fbp[i][j][k][m].cnt = 0;
tor_flag[i][j][k][m] = 0;
}
/* next line is number of 4-body params and some comments */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
l = atoi( tmp[0] );
for( i = 0; i < l; i++ ) {
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
j = atoi(tmp[0]) - 1;
k = atoi(tmp[1]) - 1;
m = atoi(tmp[2]) - 1;
n = atoi(tmp[3]) - 1;
if (j >= 0 && n >= 0) { // this means the entry is not in compact form
if (j < reax->num_atom_types && k < reax->num_atom_types &&
m < reax->num_atom_types && n < reax->num_atom_types) {
/* these flags ensure that this entry take precedence
over the compact form entries */
tor_flag[j][k][m][n] = 1;
tor_flag[n][m][k][j] = 1;
reax->fbp[j][k][m][n].cnt = 1;
reax->fbp[n][m][k][j].cnt = 1;
/* cnt = reax->fbp[j][k][m][n].cnt;
reax->fbp[j][k][m][n].cnt++;
reax->fbp[n][m][k][j].cnt++; */
val = atof(tmp[4]);
reax->fbp[j][k][m][n].prm[0].V1 = val;
reax->fbp[n][m][k][j].prm[0].V1 = val;
val = atof(tmp[5]);
reax->fbp[j][k][m][n].prm[0].V2 = val;
reax->fbp[n][m][k][j].prm[0].V2 = val;
val = atof(tmp[6]);
reax->fbp[j][k][m][n].prm[0].V3 = val;
reax->fbp[n][m][k][j].prm[0].V3 = val;
val = atof(tmp[7]);
reax->fbp[j][k][m][n].prm[0].p_tor1 = val;
reax->fbp[n][m][k][j].prm[0].p_tor1 = val;
val = atof(tmp[8]);
reax->fbp[j][k][m][n].prm[0].p_cot1 = val;
reax->fbp[n][m][k][j].prm[0].p_cot1 = val;
}
}
else { /* This means the entry is of the form 0-X-Y-0 */
if( k < reax->num_atom_types && m < reax->num_atom_types )
for( p = 0; p < reax->num_atom_types; p++ )
for( o = 0; o < reax->num_atom_types; o++ ) {
reax->fbp[p][k][m][o].cnt = 1;
reax->fbp[o][m][k][p].cnt = 1;
/* cnt = reax->fbp[p][k][m][o].cnt;
reax->fbp[p][k][m][o].cnt++;
reax->fbp[o][m][k][p].cnt++; */
if (tor_flag[p][k][m][o] == 0) {
reax->fbp[p][k][m][o].prm[0].V1 = atof(tmp[4]);
reax->fbp[p][k][m][o].prm[0].V2 = atof(tmp[5]);
reax->fbp[p][k][m][o].prm[0].V3 = atof(tmp[6]);
reax->fbp[p][k][m][o].prm[0].p_tor1 = atof(tmp[7]);
reax->fbp[p][k][m][o].prm[0].p_cot1 = atof(tmp[8]);
}
if (tor_flag[o][m][k][p] == 0) {
reax->fbp[o][m][k][p].prm[0].V1 = atof(tmp[4]);
reax->fbp[o][m][k][p].prm[0].V2 = atof(tmp[5]);
reax->fbp[o][m][k][p].prm[0].V3 = atof(tmp[6]);
reax->fbp[o][m][k][p].prm[0].p_tor1 = atof(tmp[7]);
reax->fbp[o][m][k][p].prm[0].p_cot1 = atof(tmp[8]);
}
}
}
}
/* next line is number of hydrogen bond params and some comments */
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
l = atoi( tmp[0] );
for( i = 0; i < l; i++ ) {
fgets( s, MAX_LINE, fp );
c = Tokenize( s, &tmp );
j = atoi(tmp[0]) - 1;
k = atoi(tmp[1]) - 1;
m = atoi(tmp[2]) - 1;
if( j < reax->num_atom_types && m < reax->num_atom_types ) {
val = atof(tmp[3]);
reax->hbp[j][k][m].r0_hb = val;
val = atof(tmp[4]);
reax->hbp[j][k][m].p_hb1 = val;
val = atof(tmp[5]);
reax->hbp[j][k][m].p_hb2 = val;
val = atof(tmp[6]);
reax->hbp[j][k][m].p_hb3 = val;
}
}
/* deallocate helper storage */
for( i = 0; i < MAX_TOKENS; i++ )
free( tmp[i] );
free( tmp );
free( s );
/* deallocate tor_flag */
for( i = 0; i < reax->num_atom_types; i++ ) {
for( j = 0; j < reax->num_atom_types; j++ ) {
for( k = 0; k < reax->num_atom_types; k++ ) {
free( tor_flag[i][j][k] );
}
free( tor_flag[i][j] );
}
free( tor_flag[i] );
}
free( tor_flag );
// close file
fclose(fp);
#if defined(DEBUG_FOCUS)
fprintf( stderr, "force field read\n" );
#endif
return SUCCESS;
}

View File

@ -0,0 +1,29 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __FFIELD_H_
#define __FFIELD_H_
#include "reaxc_types.h"
char Read_Force_Field( char*, reax_interaction*, control_params* );
#endif

View File

@ -0,0 +1,929 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "forces.h"
#include "bond_orders.h"
#include "bonds.h"
#include "basic_comm.h"
#include "hydrogen_bonds.h"
#include "io_tools.h"
#include "list.h"
#include "lookup.h"
#include "multi_body.h"
#include "nonbonded.h"
#include "qEq.h"
#include "tool_box.h"
#include "torsion_angles.h"
#include "valence_angles.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_forces.h"
#include "reaxc_bond_orders.h"
#include "reaxc_bonds.h"
#include "reaxc_basic_comm.h"
#include "reaxc_hydrogen_bonds.h"
#include "reaxc_io_tools.h"
#include "reaxc_list.h"
#include "reaxc_lookup.h"
#include "reaxc_multi_body.h"
#include "reaxc_nonbonded.h"
#include "reaxc_tool_box.h"
#include "reaxc_torsion_angles.h"
#include "reaxc_valence_angles.h"
#include "reaxc_vector.h"
#endif
interaction_function Interaction_Functions[NUM_INTRS];
void Dummy_Interaction( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control )
{
}
void Init_Force_Functions( control_params *control )
{
Interaction_Functions[0] = BO;
Interaction_Functions[1] = Bonds; //Dummy_Interaction;
Interaction_Functions[2] = Atom_Energy; //Dummy_Interaction;
Interaction_Functions[3] = Valence_Angles; //Dummy_Interaction;
Interaction_Functions[4] = Torsion_Angles; //Dummy_Interaction;
if( control->hbond_cut > 0 )
Interaction_Functions[5] = Hydrogen_Bonds;
else Interaction_Functions[5] = Dummy_Interaction;
Interaction_Functions[6] = Dummy_Interaction; //empty
Interaction_Functions[7] = Dummy_Interaction; //empty
Interaction_Functions[8] = Dummy_Interaction; //empty
Interaction_Functions[9] = Dummy_Interaction; //empty
}
void Compute_Bonded_Forces( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
MPI_Comm comm )
{
int i;
/* Mark beginning of a new timestep in bonded energy files */
#if defined(TEST_ENERGY)
Debug_Marker_Bonded( out_control, data->step );
#endif
/* Implement all force calls as function pointers */
for( i = 0; i < NUM_INTRS; i++ ) {
#if defined(DEBUG)
fprintf( stderr, "p%d: starting f%d\n", system->my_rank, i );
MPI_Barrier( comm );
#endif
(Interaction_Functions[i])( system, control, data, workspace,
lists, out_control );
#if defined(DEBUG)
fprintf( stderr, "p%d: f%d done\n", system->my_rank, i );
MPI_Barrier( comm );
#endif
}
}
void Compute_NonBonded_Forces( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
MPI_Comm comm )
{
/* Mark beginning of a new timestep in nonbonded energy files */
#if defined(TEST_ENERGY)
Debug_Marker_Nonbonded( out_control, data->step );
#endif
/* van der Waals and Coulomb interactions */
if( control->tabulate == 0 )
vdW_Coulomb_Energy( system, control, data, workspace,
lists, out_control );
else
Tabulated_vdW_Coulomb_Energy( system, control, data, workspace,
lists, out_control );
#if defined(DEBUG)
fprintf( stderr, "p%d: nonbonded forces done\n", system->my_rank );
MPI_Barrier( comm );
#endif
}
/* this version of Compute_Total_Force computes forces from
coefficients accumulated by all interaction functions.
Saves enormous time & space! */
void Compute_Total_Force( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, mpi_datatypes *mpi_data )
{
int i, pj;
reax_list *bonds = (*lists) + BONDS;
for( i = 0; i < system->N; ++i )
for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
if( i < bonds->select.bond_list[pj].nbr ) {
if( control->virial == 0 )
Add_dBond_to_Forces( i, pj, workspace, lists );
else
Add_dBond_to_Forces_NPT( i, pj, data, workspace, lists );
}
//Print_Total_Force( system, data, workspace );
#if defined(PURE_REAX)
/* now all forces are computed to their partially-final values
based on the neighbors information each processor has had.
final values of force on each atom needs to be computed by adding up
all partially-final pieces */
Coll( system, mpi_data, workspace->f, mpi_data->mpi_rvec,
sizeof(rvec)/sizeof(void), rvec_unpacker );
for( i = 0; i < system->n; ++i )
rvec_Copy( system->my_atoms[i].f, workspace->f[i] );
#if defined(TEST_FORCES)
Coll( system, mpi_data, workspace->f_ele, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_vdw, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_be, mpi_data->mpi_rvec, rvec_unpacker );
Coll( system, mpi_data, workspace->f_lp, mpi_data->mpi_rvec, rvec_unpacker );
Coll( system, mpi_data, workspace->f_ov, mpi_data->mpi_rvec, rvec_unpacker );
Coll( system, mpi_data, workspace->f_un, mpi_data->mpi_rvec, rvec_unpacker );
Coll( system, mpi_data, workspace->f_ang, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_coa, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_pen, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_hb, mpi_data->mpi_rvec, rvec_unpacker );
Coll( system, mpi_data, workspace->f_tor, mpi_data->mpi_rvec, rvec_unpacker);
Coll( system, mpi_data, workspace->f_con, mpi_data->mpi_rvec, rvec_unpacker);
#endif
#endif
}
void Validate_Lists( reax_system *system, storage *workspace, reax_list **lists,
int step, int n, int N, int numH, MPI_Comm comm )
{
int i, comp, Hindex;
reax_list *bonds, *hbonds;
reallocate_data *realloc;
realloc = &(workspace->realloc);
/* bond list */
if( N > 0 ) {
bonds = *lists + BONDS;
for( i = 0; i < N; ++i ) {
// if( i < n ) - we need to update ghost estimates for delayed nbrings
system->my_atoms[i].num_bonds = MAX(Num_Entries(i,bonds)*2, MIN_BONDS);
//if( End_Index(i, bonds) >= Start_Index(i+1, bonds)-2 )
//workspace->realloc.bonds = 1;
if( i < N-1 )
comp = Start_Index(i+1, bonds);
else comp = bonds->num_intrs;
if( End_Index(i, bonds) > comp ) {
fprintf( stderr, "step%d-bondchk failed: i=%d end(i)=%d str(i+1)=%d\n",
step, i, End_Index(i,bonds), comp );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
}
}
/* hbonds list */
if( numH > 0 ) {
hbonds = *lists + HBONDS;
for( i = 0; i < n; ++i ) {
Hindex = system->my_atoms[i].Hindex;
if( Hindex > -1 ) {
system->my_atoms[i].num_hbonds =
(int)(MAX( Num_Entries(Hindex, hbonds)*SAFER_ZONE, MIN_HBONDS ));
//if( Num_Entries(i, hbonds) >=
//(Start_Index(i+1,hbonds)-Start_Index(i,hbonds))*0.90/*DANGER_ZONE*/){
// workspace->realloc.hbonds = 1;
if( Hindex < numH-1 )
comp = Start_Index(Hindex+1, hbonds);
else comp = hbonds->num_intrs;
if( End_Index(Hindex, hbonds) > comp ) {
fprintf(stderr,"step%d-hbondchk failed: H=%d end(H)=%d str(H+1)=%d\n",
step, Hindex, End_Index(Hindex,hbonds), comp );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
}
}
}
}
real Compute_H( real r, real gamma, real *ctap )
{
real taper, dr3gamij_1, dr3gamij_3;
taper = ctap[7] * r + ctap[6];
taper = taper * r + ctap[5];
taper = taper * r + ctap[4];
taper = taper * r + ctap[3];
taper = taper * r + ctap[2];
taper = taper * r + ctap[1];
taper = taper * r + ctap[0];
dr3gamij_1 = ( r*r*r + gamma );
dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 );
return taper * EV_to_KCALpMOL / dr3gamij_3;
}
real Compute_tabH( real r_ij, int ti, int tj )
{
int r, tmin, tmax;
real val, dif, base;
LR_lookup_table *t;
tmin = MIN( ti, tj );
tmax = MAX( ti, tj );
t = &( LR[tmin][tmax] );
/* cubic spline interpolation */
r = (int)(r_ij * t->inv_dx);
if( r == 0 ) ++r;
base = (real)(r+1) * t->dx;
dif = r_ij - base;
val = ((t->ele[r].d*dif + t->ele[r].c)*dif + t->ele[r].b)*dif +
t->ele[r].a;
val *= EV_to_KCALpMOL / C_ele;
return val;
}
void Init_Forces( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
output_controls *out_control, MPI_Comm comm ) {
int i, j, pj;
int start_i, end_i;
int type_i, type_j;
int Htop, btop_i, btop_j, num_bonds, num_hbonds;
int ihb, jhb, ihb_top, jhb_top;
int local, flag, renbr;
real r_ij, cutoff;
sparse_matrix *H;
reax_list *far_nbrs, *bonds, *hbonds;
single_body_parameters *sbp_i, *sbp_j;
two_body_parameters *twbp;
far_neighbor_data *nbr_pj;
reax_atom *atom_i, *atom_j;
far_nbrs = *lists + FAR_NBRS;
bonds = *lists + BONDS;
hbonds = *lists + HBONDS;
for( i = 0; i < system->n; ++i )
workspace->bond_mark[i] = 0;
for( i = system->n; i < system->N; ++i ) {
workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance
//workspace->done_after[i] = Start_Index( i, far_nbrs );
}
H = workspace->H;
H->n = system->n;
Htop = 0;
num_bonds = 0;
num_hbonds = 0;
btop_i = btop_j = 0;
renbr = (data->step-data->prev_steps) % control->reneighbor == 0;
for( i = 0; i < system->N; ++i ) {
atom_i = &(system->my_atoms[i]);
type_i = atom_i->type;
start_i = Start_Index(i, far_nbrs);
end_i = End_Index(i, far_nbrs);
btop_i = End_Index( i, bonds );
sbp_i = &(system->reax_param.sbp[type_i]);
if( i < system->n ) {
local = 1;
cutoff = control->nonb_cut;
}
else {
local = 0;
cutoff = control->bond_cut;
}
ihb = -1;
ihb_top = -1;
if( local ) {
H->start[i] = Htop;
H->entries[Htop].j = i;
H->entries[Htop].val = sbp_i->eta;
++Htop;
if( control->hbond_cut > 0 ) {
ihb = sbp_i->p_hbond;
if( ihb == 1 )
ihb_top = End_Index( atom_i->Hindex, hbonds );
else ihb_top = -1;
}
}
/* update i-j distance - check if j is within cutoff */
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
j = nbr_pj->nbr;
atom_j = &(system->my_atoms[j]);
//fprintf( stderr, "%d%d i=%d x_i: %f %f %f,j=%d x_j: %f %f %f, d=%f\n",
// MIN(atom_i->orig_id, atom_j->orig_id),
// MAX(atom_i->orig_id, atom_j->orig_id),
// i, atom_i->x[0], atom_i->x[1], atom_i->x[2],
// j, atom_j->x[0], atom_j->x[1], atom_j->x[2], nbr_pj->d );
if( renbr ) {
if(nbr_pj->d <= cutoff)
flag = 1;
else flag = 0;
}
else{
nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0];
nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1];
nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2];
nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec );
if( nbr_pj->d <= SQR(cutoff) ) {
nbr_pj->d = sqrt(nbr_pj->d);
flag = 1;
}
else {
flag = 0;
}
}
if( flag ){
type_j = atom_j->type;
r_ij = nbr_pj->d;
sbp_j = &(system->reax_param.sbp[type_j]);
twbp = &(system->reax_param.tbp[type_i][type_j]);
if( local ) {
/* H matrix entry */
if( j < system->n || atom_i->orig_id < atom_j->orig_id ) {//tryQEq||1
H->entries[Htop].j = j;
//fprintf( stdout, "%d%d %d %d\n",
// MIN(atom_i->orig_id, atom_j->orig_id),
// MAX(atom_i->orig_id, atom_j->orig_id),
// MIN(atom_i->orig_id, atom_j->orig_id),
// MAX(atom_i->orig_id, atom_j->orig_id) );
if( control->tabulate == 0 )
H->entries[Htop].val = Compute_H(r_ij,twbp->gamma,workspace->Tap);
else H->entries[Htop].val = Compute_tabH(r_ij, type_i, type_j);
++Htop;
}
/* hydrogen bond lists */
if( control->hbond_cut > 0 && (ihb==1 || ihb==2) &&
nbr_pj->d <= control->hbond_cut ) {
// fprintf( stderr, "%d %d\n", atom1, atom2 );
jhb = sbp_j->p_hbond;
if( ihb == 1 && jhb == 2 ) {
hbonds->select.hbond_list[ihb_top].nbr = j;
hbonds->select.hbond_list[ihb_top].scl = 1;
hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
++ihb_top;
++num_hbonds;
}
else if( j < system->n && ihb == 2 && jhb == 1 ) {
jhb_top = End_Index( atom_j->Hindex, hbonds );
hbonds->select.hbond_list[jhb_top].nbr = i;
hbonds->select.hbond_list[jhb_top].scl = -1;
hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds );
++num_hbonds;
}
}
}
/* uncorrected bond orders */
if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) &&
nbr_pj->d <= control->bond_cut &&
BOp( workspace, bonds, control->bo_cut,
i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
num_bonds += 2;
++btop_i;
if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) {
workspace->bond_mark[i] = workspace->bond_mark[j] + 1;
//if( workspace->bond_mark[i] == 1000 )
// workspace->done_after[i] = pj;
}
//fprintf( stdout, "%d%d - %d(%d) %d(%d)\n",
// i , j, i, workspace->bond_mark[i], j, workspace->bond_mark[j] );
}
}
}
Set_End_Index( i, btop_i, bonds );
if( local ) {
H->end[i] = Htop;
if( ihb == 1 )
Set_End_Index( atom_i->Hindex, ihb_top, hbonds );
}
}
//fprintf( stderr, "after the first init loop\n" );
/*for( i = system->n; i < system->N; ++i )
if( workspace->bond_mark[i] > 3 ) {
start_i = Start_Index(i, bonds);
end_i = End_Index(i, bonds);
num_bonds -= (end_i - start_i);
Set_End_Index(i, start_i, bonds );
}*/
/*for( i = system->n; i < system->N; ++i ) {
start_i = Start_Index(i, far_nbrs);
end_i = workspace->done_after[i];
if( workspace->bond_mark[i] >= 2 && start_i < end_i ) {
atom_i = &(system->my_atoms[i]);
type_i = atom_i->type;
btop_i = End_Index( i, bonds );
sbp_i = &(system->reax_param.sbp[type_i]);
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
j = nbr_pj->nbr;
if( workspace->bond_mark[j] >= 2 && nbr_pj->d <= control->bond_cut ) {
atom_j = &(system->my_atoms[j]);
type_j = atom_j->type;
sbp_j = &(system->reax_param.sbp[type_j]);
twbp = &(system->reax_param.tbp[type_i][type_j]);
if( BOp( workspace, bonds, control->bo_cut,
i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
num_bonds += 2;
++btop_i;
if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 )
workspace->bond_mark[i] = workspace->bond_mark[j] + 1;
//fprintf( stdout, "%d%d - %d(%d) %d(%d) new\n",
// i , j, i, workspace->bond_mark[i], j, workspace->bond_mark[j] );
}
}
}
Set_End_Index( i, btop_i, bonds );
}
}*/
workspace->realloc.Htop = Htop;
workspace->realloc.num_bonds = num_bonds;
workspace->realloc.num_hbonds = num_hbonds;
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: Htop = %d num_bonds = %d num_hbonds = %d\n",
system->my_rank, data->step, Htop, num_bonds, num_hbonds );
MPI_Barrier( comm );
#endif
#if defined( DEBUG )
Print_Bonds( system, bonds, "debugbonds.out" );
Print_Bond_List2( system, bonds, "pbonds.out" );
Print_Sparse_Matrix( system, H );
for( i = 0; i < H->n; ++i )
for( j = H->start[i]; j < H->end[i]; ++j )
fprintf( stderr, "%d %d %.15e\n",
MIN(system->my_atoms[i].orig_id,
system->my_atoms[H->entries[j].j].orig_id),
MAX(system->my_atoms[i].orig_id,
system->my_atoms[H->entries[j].j].orig_id),
H->entries[j].val );
#endif
Validate_Lists( system, workspace, lists, data->step,
system->n, system->N, system->numH, comm );
}
void Init_Forces_noQEq( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
MPI_Comm comm ) {
int i, j, pj;
int start_i, end_i;
int type_i, type_j;
int btop_i, btop_j, num_bonds, num_hbonds;
int ihb, jhb, ihb_top, jhb_top;
int local, flag, renbr;
real r_ij, cutoff;
reax_list *far_nbrs, *bonds, *hbonds;
single_body_parameters *sbp_i, *sbp_j;
two_body_parameters *twbp;
far_neighbor_data *nbr_pj;
reax_atom *atom_i, *atom_j;
far_nbrs = *lists + FAR_NBRS;
bonds = *lists + BONDS;
hbonds = *lists + HBONDS;
for( i = 0; i < system->n; ++i )
workspace->bond_mark[i] = 0;
for( i = system->n; i < system->N; ++i ) {
workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance
//workspace->done_after[i] = Start_Index( i, far_nbrs );
}
num_bonds = 0;
num_hbonds = 0;
btop_i = btop_j = 0;
renbr = (data->step-data->prev_steps) % control->reneighbor == 0;
for( i = 0; i < system->N; ++i ) {
atom_i = &(system->my_atoms[i]);
type_i = atom_i->type;
start_i = Start_Index(i, far_nbrs);
end_i = End_Index(i, far_nbrs);
btop_i = End_Index( i, bonds );
sbp_i = &(system->reax_param.sbp[type_i]);
if( i < system->n ) {
local = 1;
cutoff = MAX( control->hbond_cut, control->bond_cut );
}
else {
local = 0;
cutoff = control->bond_cut;
}
ihb = -1;
ihb_top = -1;
if( local && control->hbond_cut > 0 ) {
ihb = sbp_i->p_hbond;
if( ihb == 1 )
ihb_top = End_Index( atom_i->Hindex, hbonds );
else ihb_top = -1;
}
/* update i-j distance - check if j is within cutoff */
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
j = nbr_pj->nbr;
atom_j = &(system->my_atoms[j]);
if( renbr ) {
if( nbr_pj->d <= cutoff )
flag = 1;
else flag = 0;
}
else{
nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0];
nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1];
nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2];
nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec );
if( nbr_pj->d <= SQR(cutoff) ) {
nbr_pj->d = sqrt(nbr_pj->d);
flag = 1;
}
else {
flag = 0;
}
}
if( flag ) {
type_j = atom_j->type;
r_ij = nbr_pj->d;
sbp_j = &(system->reax_param.sbp[type_j]);
twbp = &(system->reax_param.tbp[type_i][type_j]);
if( local ) {
/* hydrogen bond lists */
if( control->hbond_cut > 0 && (ihb==1 || ihb==2) &&
nbr_pj->d <= control->hbond_cut ) {
// fprintf( stderr, "%d %d\n", atom1, atom2 );
jhb = sbp_j->p_hbond;
if( ihb == 1 && jhb == 2 ) {
hbonds->select.hbond_list[ihb_top].nbr = j;
hbonds->select.hbond_list[ihb_top].scl = 1;
hbonds->select.hbond_list[ihb_top].ptr = nbr_pj;
++ihb_top;
++num_hbonds;
}
else if( j < system->n && ihb == 2 && jhb == 1 ) {
jhb_top = End_Index( atom_j->Hindex, hbonds );
hbonds->select.hbond_list[jhb_top].nbr = i;
hbonds->select.hbond_list[jhb_top].scl = -1;
hbonds->select.hbond_list[jhb_top].ptr = nbr_pj;
Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds );
++num_hbonds;
}
}
}
/* uncorrected bond orders */
if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) &&
nbr_pj->d <= control->bond_cut &&
BOp( workspace, bonds, control->bo_cut,
i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) {
num_bonds += 2;
++btop_i;
if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 )
workspace->bond_mark[j] = workspace->bond_mark[i] + 1;
else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) {
workspace->bond_mark[i] = workspace->bond_mark[j] + 1;
//if( workspace->bond_mark[i] == 1000 )
// workspace->done_after[i] = pj;
}
//fprintf( stdout, "%d%d - %d(%d) %d(%d)\n",
// i , j, i, workspace->bond_mark[i], j, workspace->bond_mark[j] );
}
}
}
Set_End_Index( i, btop_i, bonds );
if( local && ihb == 1 )
Set_End_Index( atom_i->Hindex, ihb_top, hbonds );
}
/*for( i = system->n; i < system->N; ++i )
if( workspace->bond_mark[i] > 3 ) {
start_i = Start_Index(i, bonds);
end_i = End_Index(i, bonds);
num_bonds -= (end_i - start_i);
Set_End_Index(i, start_i, bonds );
}*/
workspace->realloc.num_bonds = num_bonds;
workspace->realloc.num_hbonds = num_hbonds;
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: num_bonds = %d num_hbonds = %d\n",
system->my_rank, data->step, num_bonds, num_hbonds );
MPI_Barrier( comm );
#endif
#if defined( DEBUG )
Print_Bonds( system, bonds, "debugbonds.out" );
Print_Bond_List2( system, bonds, "pbonds.out" );
#endif
Validate_Lists( system, workspace, lists, data->step,
system->n, system->N, system->numH, comm );
}
void Estimate_Storages( reax_system *system, control_params *control,
reax_list **lists, int *Htop, int *hb_top,
int *bond_top, int *num_3body, MPI_Comm comm )
{
int i, j, pj;
int start_i, end_i;
int type_i, type_j;
int ihb, jhb;
int local;
real cutoff;
real r_ij, r2;
real C12, C34, C56;
real BO, BO_s, BO_pi, BO_pi2;
reax_list *far_nbrs;
single_body_parameters *sbp_i, *sbp_j;
two_body_parameters *twbp;
far_neighbor_data *nbr_pj;
reax_atom *atom_i, *atom_j;
far_nbrs = *lists + FAR_NBRS;
*Htop = 0;
memset( hb_top, 0, sizeof(int) * system->local_cap );
memset( bond_top, 0, sizeof(int) * system->total_cap );
*num_3body = 0;
for( i = 0; i < system->N; ++i ) {
atom_i = &(system->my_atoms[i]);
type_i = atom_i->type;
start_i = Start_Index(i, far_nbrs);
end_i = End_Index(i, far_nbrs);
sbp_i = &(system->reax_param.sbp[type_i]);
if( i < system->n ) {
local = 1;
cutoff = control->nonb_cut;
++(*Htop);
ihb = sbp_i->p_hbond;
}
else {
local = 0;
cutoff = control->bond_cut;
ihb = -1;
}
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &( far_nbrs->select.far_nbr_list[pj] );
j = nbr_pj->nbr;
atom_j = &(system->my_atoms[j]);
if(nbr_pj->d <= cutoff) {
type_j = system->my_atoms[j].type;
r_ij = nbr_pj->d;
sbp_j = &(system->reax_param.sbp[type_j]);
twbp = &(system->reax_param.tbp[type_i][type_j]);
if( local ) {
if( j < system->n || atom_i->orig_id < atom_j->orig_id ) //tryQEq ||1
++(*Htop);
/* hydrogen bond lists */
if( control->hbond_cut > 0.1 && (ihb==1 || ihb==2) &&
nbr_pj->d <= control->hbond_cut ) {
jhb = sbp_j->p_hbond;
if( ihb == 1 && jhb == 2 )
++hb_top[i];
else if( j < system->n && ihb == 2 && jhb == 1 )
++hb_top[j];
}
}
/* uncorrected bond orders */
if( nbr_pj->d <= control->bond_cut ) {
r2 = SQR(r_ij);
if( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) {
C12 = twbp->p_bo1 * pow( r_ij / twbp->r_s, twbp->p_bo2 );
BO_s = (1.0 + control->bo_cut) * exp( C12 );
}
else BO_s = C12 = 0.0;
if( sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) {
C34 = twbp->p_bo3 * pow( r_ij / twbp->r_p, twbp->p_bo4 );
BO_pi = exp( C34 );
}
else BO_pi = C34 = 0.0;
if( sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) {
C56 = twbp->p_bo5 * pow( r_ij / twbp->r_pp, twbp->p_bo6 );
BO_pi2= exp( C56 );
}
else BO_pi2 = C56 = 0.0;
/* Initially BO values are the uncorrected ones, page 1 */
BO = BO_s + BO_pi + BO_pi2;
if( BO >= control->bo_cut ) {
++bond_top[i];
++bond_top[j];
}
}
}
}
}
*Htop = (int)(MAX( *Htop * SAFE_ZONE, MIN_CAP * MIN_HENTRIES ));
for( i = 0; i < system->n; ++i )
hb_top[i] = (int)(MAX( hb_top[i] * SAFER_ZONE, MIN_HBONDS ));
for( i = 0; i < system->N; ++i ) {
*num_3body += SQR(bond_top[i]);
//if( i < system->n )
bond_top[i] = MAX( bond_top[i] * 2, MIN_BONDS );
//else bond_top[i] = MAX_BONDS;
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ estimate storages: Htop = %d, num_3body = %d\n",
system->my_rank, *Htop, *num_3body );
MPI_Barrier( comm );
#endif
}
void Compute_Forces( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
mpi_datatypes *mpi_data )
{
MPI_Comm comm;
int qeq_flag;
#if defined(LOG_PERFORMANCE)
real t_start = 0;
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
t_start = Get_Time( );
#endif
comm = mpi_data->world;
/********* init forces ************/
#if defined(PURE_REAX)
if( control->qeq_freq && (data->step-data->prev_steps)%control->qeq_freq==0 )
qeq_flag = 1;
else qeq_flag = 0;
#elif defined(LAMMPS_REAX)
qeq_flag = 0;
#endif
if( qeq_flag )
Init_Forces( system, control, data, workspace, lists, out_control, comm );
else
Init_Forces_noQEq( system, control, data, workspace,
lists, out_control, comm );
#if defined(LOG_PERFORMANCE)
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
Update_Timing_Info( &t_start, &(data->timing.init_forces) );
#endif
/********* bonded interactions ************/
Compute_Bonded_Forces( system, control, data, workspace,
lists, out_control, mpi_data->world );
#if defined(LOG_PERFORMANCE)
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
Update_Timing_Info( &t_start, &(data->timing.bonded) );
#endif
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: completed bonded\n",
system->my_rank, data->step );
MPI_Barrier( mpi_data->world );
#endif
/**************** qeq ************************/
#if defined(PURE_REAX)
if( qeq_flag )
QEq( system, control, data, workspace, out_control, mpi_data );
#if defined(LOG_PERFORMANCE)
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
Update_Timing_Info( &t_start, &(data->timing.qEq) );
#endif
#if defined(DEBUG_FOCUS)
fprintf(stderr, "p%d @ step%d: qeq completed\n", system->my_rank, data->step);
MPI_Barrier( mpi_data->world );
#endif
#endif //PURE_REAX
/********* nonbonded interactions ************/
Compute_NonBonded_Forces( system, control, data, workspace,
lists, out_control, mpi_data->world );
#if defined(LOG_PERFORMANCE)
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
Update_Timing_Info( &t_start, &(data->timing.nonb) );
#endif
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: nonbonded forces completed\n",
system->my_rank, data->step );
MPI_Barrier( mpi_data->world );
#endif
/*********** total force ***************/
Compute_Total_Force( system, control, data, workspace, lists, mpi_data );
#if defined(LOG_PERFORMANCE)
//MPI_Barrier( mpi_data->world );
if( system->my_rank == MASTER_NODE )
Update_Timing_Info( &t_start, &(data->timing.bonded) );
#endif
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: total forces computed\n",
system->my_rank, data->step );
//Print_Total_Force( system, data, workspace );
MPI_Barrier( mpi_data->world );
#endif
#if defined(TEST_FORCES)
Print_Force_Files( system, control, data, workspace,
lists, out_control, mpi_data );
#endif
}

View File

@ -0,0 +1,35 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __FORCES_H_
#define __FORCES_H_
#include "reaxc_types.h"
#include "reaxc_defs.h"
extern interaction_function Interaction_Functions[NUM_INTRS];
void Init_Force_Functions( control_params* );
void Compute_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls*, mpi_datatypes* );
void Estimate_Storages( reax_system*, control_params*, reax_list**,
int*, int*, int*, int*, MPI_Comm );
#endif

View File

@ -0,0 +1,220 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "hydrogen_bonds.h"
#include "bond_orders.h"
#include "list.h"
#include "valence_angles.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_hydrogen_bonds.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_valence_angles.h"
#include "reaxc_vector.h"
#endif
void Hydrogen_Bonds( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control )
{
int i, j, k, pi, pk;
int type_i, type_j, type_k;
int start_j, end_j, hb_start_j, hb_end_j;
int hblist[MAX_BONDS];
int itr, top;
int num_hb_intrs = 0;
ivec rel_jk;
real r_ij, r_jk, theta, cos_theta, sin_xhz4, cos_xhz1, sin_theta2;
real e_hb, exp_hb2, exp_hb3, CEhb1, CEhb2, CEhb3;
rvec dcos_theta_di, dcos_theta_dj, dcos_theta_dk;
rvec dvec_jk, force, ext_press;
// rtensor temp_rtensor, total_rtensor;
hbond_parameters *hbp;
bond_order_data *bo_ij;
bond_data *pbond_ij;
far_neighbor_data *nbr_jk;
reax_list *bonds, *hbonds;
bond_data *bond_list;
hbond_data *hbond_list;
bonds = (*lists) + BONDS;
bond_list = bonds->select.bond_list;
hbonds = (*lists) + HBONDS;
hbond_list = hbonds->select.hbond_list;
/* loops below discover the Hydrogen bonds between i-j-k triplets.
here j is H atom and there has to be some bond between i and j.
Hydrogen bond is between j and k.
so in this function i->X, j->H, k->Z when we map
variables onto the ones in the handout.*/
for( j = 0; j < system->n; ++j )
/* j has to be of type H */
if( system->reax_param.sbp[system->my_atoms[j].type].p_hbond == 1 ) {
/*set j's variables */
type_j = system->my_atoms[j].type;
start_j = Start_Index(j, bonds);
end_j = End_Index(j, bonds);
hb_start_j = Start_Index( system->my_atoms[j].Hindex, hbonds );
hb_end_j = End_Index( system->my_atoms[j].Hindex, hbonds );
top = 0;
for( pi = start_j; pi < end_j; ++pi ) {
pbond_ij = &( bond_list[pi] );
i = pbond_ij->nbr;
bo_ij = &(pbond_ij->bo_data);
type_i = system->my_atoms[i].type;
if( system->reax_param.sbp[type_i].p_hbond == 2 &&
bo_ij->BO >= HB_THRESHOLD )
hblist[top++] = pi;
}
// fprintf( stderr, "j: %d, top: %d, hb_start_j: %d, hb_end_j:%d\n",
// j, top, hb_start_j, hb_end_j );
for( pk = hb_start_j; pk < hb_end_j; ++pk ) {
/* set k's varibles */
k = hbond_list[pk].nbr;
type_k = system->my_atoms[k].type;
nbr_jk = hbond_list[pk].ptr;
r_jk = nbr_jk->d;
rvec_Scale( dvec_jk, hbond_list[pk].scl, nbr_jk->dvec );
for( itr = 0; itr < top; ++itr ) {
pi = hblist[itr];
pbond_ij = &( bonds->select.bond_list[pi] );
i = pbond_ij->nbr;
if( system->my_atoms[i].orig_id != system->my_atoms[k].orig_id ) {
bo_ij = &(pbond_ij->bo_data);
type_i = system->my_atoms[i].type;
r_ij = pbond_ij->d;
hbp = &(system->reax_param.hbp[ type_i ][ type_j ][ type_k ]);
++num_hb_intrs;
Calculate_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk,
&theta, &cos_theta );
/* the derivative of cos(theta) */
Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk,
&dcos_theta_di, &dcos_theta_dj,
&dcos_theta_dk );
/* hyrogen bond energy*/
sin_theta2 = sin( theta/2.0 );
sin_xhz4 = SQR(sin_theta2);
sin_xhz4 *= sin_xhz4;
cos_xhz1 = ( 1.0 - cos_theta );
exp_hb2 = exp( -hbp->p_hb2 * bo_ij->BO );
exp_hb3 = exp( -hbp->p_hb3 * ( hbp->r0_hb / r_jk +
r_jk / hbp->r0_hb - 2.0 ) );
data->my_en.e_hb += e_hb =
hbp->p_hb1 * (1.0 - exp_hb2) * exp_hb3 * sin_xhz4;
CEhb1 = hbp->p_hb1 * hbp->p_hb2 * exp_hb2 * exp_hb3 * sin_xhz4;
CEhb2 = -hbp->p_hb1/2.0 * (1.0 - exp_hb2) * exp_hb3 * cos_xhz1;
CEhb3 = -hbp->p_hb3 *
(-hbp->r0_hb / SQR(r_jk) + 1.0 / hbp->r0_hb) * e_hb;
/*fprintf( stdout,
"%6d%6d%6d%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
r_jk, theta, hbp->p_hb1, exp_hb2, hbp->p_hb3, hbp->r0_hb,
exp_hb3, sin_xhz4, e_hb ); */
/* hydrogen bond forces */
bo_ij->Cdbo += CEhb1; // dbo term
if( control->virial == 0 ) {
// dcos terms
rvec_ScaledAdd( workspace->f[i], +CEhb2, dcos_theta_di );
rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj );
rvec_ScaledAdd( workspace->f[k], +CEhb2, dcos_theta_dk );
// dr terms
rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk );
rvec_ScaledAdd( workspace->f[k], +CEhb3/r_jk, dvec_jk );
}
else {
/* for pressure coupling, terms that are not related to bond order
derivatives are added directly into pressure vector/tensor */
rvec_Scale( force, +CEhb2, dcos_theta_di ); // dcos terms
rvec_Add( workspace->f[i], force );
rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );
rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj );
ivec_Scale( rel_jk, hbond_list[pk].scl, nbr_jk->rel_box );
rvec_Scale( force, +CEhb2, dcos_theta_dk );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, rel_jk, force );
rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );
// dr terms
rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk );
rvec_Scale( force, CEhb3/r_jk, dvec_jk );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, rel_jk, force );
rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press );
}
#ifdef TEST_ENERGY
/* fprintf( out_control->ehb,
"%24.15e%24.15e%24.15e\n%24.15e%24.15e%24.15e\n%24.15e%24.15e%24.15e\n",
dcos_theta_di[0], dcos_theta_di[1], dcos_theta_di[2],
dcos_theta_dj[0], dcos_theta_dj[1], dcos_theta_dj[2],
dcos_theta_dk[0], dcos_theta_dk[1], dcos_theta_dk[2]);
fprintf( out_control->ehb, "%24.15e%24.15e%24.15e\n",
CEhb1, CEhb2, CEhb3 ); */
fprintf( out_control->ehb,
//"%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
r_jk, theta, bo_ij->BO, e_hb, data->my_en.e_hb );
#endif
#ifdef TEST_FORCES
Add_dBO( system, lists, j, pi, +CEhb1, workspace->f_hb ); //dbo term
// dcos terms
rvec_ScaledAdd( workspace->f_hb[i], +CEhb2, dcos_theta_di );
rvec_ScaledAdd( workspace->f_hb[j], +CEhb2, dcos_theta_dj );
rvec_ScaledAdd( workspace->f_hb[k], +CEhb2, dcos_theta_dk );
// dr terms
rvec_ScaledAdd( workspace->f_hb[j], -CEhb3/r_jk, dvec_jk );
rvec_ScaledAdd( workspace->f_hb[k], +CEhb3/r_jk, dvec_jk );
#endif
}
}
}
}
#if defined(DEBUG)
fprintf( stderr, "Number of hydrogen bonds: %d\n", num_hb_intrs );
fprintf( stderr, "Hydrogen Bond Energy: %g\n", data->my_en.e_hb );
fprintf( stderr, "hydbonds: ext_press (%24.15e %24.15e %24.15e)\n",
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
}

View File

@ -0,0 +1,30 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __HBONDS_H_
#define __HBONDS_H_
#include "reaxc_types.h"
void Hydrogen_Bonds( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
#endif

View File

@ -0,0 +1,916 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "init_md.h"
#include "allocate.h"
#include "box.h"
#include "comm_tools.h"
#include "forces.h"
#include "grid.h"
#include "integrate.h"
#include "io_tools.h"
#include "list.h"
#include "lookup.h"
#include "neighbors.h"
#include "random.h"
#include "reset_tools.h"
#include "system_props.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_init_md.h"
#include "reaxc_allocate.h"
#include "reaxc_forces.h"
#include "reaxc_io_tools.h"
#include "reaxc_list.h"
#include "reaxc_lookup.h"
#include "reaxc_reset_tools.h"
#include "reaxc_system_props.h"
#include "reaxc_tool_box.h"
#include "reaxc_vector.h"
#endif
#if defined(PURE_REAX)
/************************ initialize system ************************/
int Reposition_Atoms( reax_system *system, control_params *control,
simulation_data *data, mpi_datatypes *mpi_data,
char *msg )
{
int i;
rvec dx;
/* reposition atoms */
if( control->reposition_atoms == 0 ) { //fit atoms to periodic box
rvec_MakeZero( dx );
}
else if( control->reposition_atoms == 1 ) { //put center of mass to center
rvec_Scale( dx, 0.5, system->big_box.box_norms );
rvec_ScaledAdd( dx, -1., data->xcm );
}
else if( control->reposition_atoms == 2 ) { //put center of mass to origin
rvec_Scale( dx, -1., data->xcm );
}
else {
strcpy( msg, "reposition_atoms: invalid option" );
return FAILURE;
}
for( i = 0; i < system->n; ++i )
// Inc_on_T3_Gen( system->my_atoms[i].x, dx, &(system->big_box) );
rvec_Add( system->my_atoms[i].x, dx );
return SUCCESS;
}
void Generate_Initial_Velocities( reax_system *system, real T )
{
int i;
real m, scale, norm;
if( T <= 0.1 ) {
for( i = 0; i < system->n; i++ )
rvec_MakeZero( system->my_atoms[i].v );
}
else {
Randomize();
for( i = 0; i < system->n; i++ ) {
rvec_Random( system->my_atoms[i].v );
norm = rvec_Norm_Sqr( system->my_atoms[i].v );
m = system->reax_param.sbp[ system->my_atoms[i].type ].mass;
scale = sqrt( m * norm / (3.0 * K_B * T) );
rvec_Scale( system->my_atoms[i].v, 1./scale, system->my_atoms[i].v );
// fprintf( stderr, "v = %f %f %f\n",
// system->my_atoms[i].v[0],
// system->my_atoms[i].v[1],
// system->my_atoms[i].v[2] );
// fprintf( stderr, "scale = %f\n", scale );
// fprintf( stderr, "v = %f %f %f\n",
// system->my_atoms[i].v[0],
// system->my_atoms[i].v[1],
// system->my_atoms[i].v[2] );
}
}
}
int Init_System( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
mpi_datatypes *mpi_data, char *msg )
{
int i;
reax_atom *atom;
int nrecv[MAX_NBRS];
Setup_New_Grid( system, control, mpi_data->world );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d GRID:\n", system->my_rank );
Print_Grid( &(system->my_grid), stderr );
#endif
Bin_My_Atoms( system, &(workspace->realloc) );
Reorder_My_Atoms( system, workspace );
/* estimate N and total capacity */
for( i = 0; i < MAX_NBRS; ++i ) nrecv[i] = 0;
system->max_recved = 0;
system->N = SendRecv( system, mpi_data, mpi_data->boundary_atom_type, nrecv,
Estimate_Boundary_Atoms, Unpack_Estimate_Message, 1 );
system->total_cap = MAX( (int)(system->N * SAFE_ZONE), MIN_CAP );
Bin_Boundary_Atoms( system );
/* estimate numH and Hcap */
system->numH = 0;
if( control->hbond_cut > 0 )
for( i = 0; i < system->n; ++i ) {
atom = &(system->my_atoms[i]);
if( system->reax_param.sbp[ atom->type ].p_hbond == 1 )
atom->Hindex = system->numH++;
else atom->Hindex = -1;
}
system->Hcap = MAX( system->numH * SAFER_ZONE, MIN_CAP );
//Allocate_System( system, system->local_cap, system->total_cap, msg );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: n=%d local_cap=%d\n",
system->my_rank, system->n, system->local_cap );
fprintf( stderr, "p%d: N=%d total_cap=%d\n",
system->my_rank, system->N, system->total_cap );
fprintf( stderr, "p%d: numH=%d H_cap=%d\n",
system->my_rank, system->numH, system->Hcap );
#endif
// if( Reposition_Atoms( system, control, data, mpi_data, msg ) == FAILURE )
// return FAILURE;
/* initialize velocities so that desired init T can be attained */
if( !control->restart || (control->restart && control->random_vel) )
Generate_Initial_Velocities( system, control->T_init );
return SUCCESS;
}
/************************ initialize simulation data ************************/
int Init_Simulation_Data( reax_system *system, control_params *control,
simulation_data *data, mpi_datatypes *mpi_data,
char *msg )
{
Reset_Simulation_Data( data, control->virial );
if( !control->restart )
data->step = data->prev_steps = 0;
Compute_Total_Mass( system, data, mpi_data->comm_mesh3D );
Compute_Center_of_Mass( system, data, mpi_data, mpi_data->comm_mesh3D );
Compute_Kinetic_Energy( system, data, mpi_data->comm_mesh3D );
switch( control->ensemble ){
case NVE:
data->N_f = 3 * system->bigN;
Evolve = Velocity_Verlet_NVE;
break;
case bNVT:
data->N_f = 3 * system->bigN + 1;
Evolve = Velocity_Verlet_Berendsen_NVT;
break;
case nhNVT:
fprintf( stderr, "WARNING: Nose-Hoover NVT is still under testing.\n" );
//return FAILURE;
data->N_f = 3 * system->bigN + 1;
Evolve = Velocity_Verlet_Nose_Hoover_NVT_Klein;
if( !control->restart || (control->restart && control->random_vel) ) {
data->therm.G_xi = control->Tau_T *
(2.0 * data->sys_en.e_kin - data->N_f * K_B * control->T );
data->therm.v_xi = data->therm.G_xi * control->dt;
data->therm.v_xi_old = 0;
data->therm.xi = 0;
}
break;
case sNPT: /* Semi-Isotropic NPT */
data->N_f = 3 * system->bigN + 4;
Evolve = Velocity_Verlet_Berendsen_NPT;
if( !control->restart )
Reset_Pressures( data );
break;
case iNPT: /* Isotropic NPT */
data->N_f = 3 * system->bigN + 2;
Evolve = Velocity_Verlet_Berendsen_NPT;
if( !control->restart )
Reset_Pressures( data );
break;
case NPT: /* Anisotropic NPT */
strcpy( msg, "init_simulation_data: option not yet implemented" );
return FAILURE;
data->N_f = 3 * system->bigN + 9;
Evolve = Velocity_Verlet_Berendsen_NPT;
/*if( !control->restart ) {
data->therm.G_xi = control->Tau_T *
(2.0 * data->my_en.e_Kin - data->N_f * K_B * control->T );
data->therm.v_xi = data->therm.G_xi * control->dt;
data->iso_bar.eps = 0.33333 * log(system->box.volume);
data->inv_W = 1.0 /
( data->N_f * K_B * control->T * SQR(control->Tau_P) );
Compute_Pressure( system, control, data, out_control );
}*/
break;
default:
strcpy( msg, "init_simulation_data: ensemble not recognized" );
return FAILURE;
}
/* initialize the timer(s) */
MPI_Barrier( mpi_data->world ); // wait for everyone to come here
if( system->my_rank == MASTER_NODE ) {
data->timing.start = Get_Time( );
#if defined(LOG_PERFORMANCE)
Reset_Timing( &data->timing );
#endif
}
#if defined(DEBUG)
fprintf( stderr, "data->N_f: %8.3f\n", data->N_f );
#endif
return SUCCESS;
}
#elif defined(LAMMPS_REAX)
int Init_System( reax_system *system, control_params *control, char *msg )
{
int i;
reax_atom *atom;
/* determine the local and total capacity */
system->local_cap = MAX( (int)(system->n * SAFE_ZONE), MIN_CAP );
system->total_cap = MAX( (int)(system->N * SAFE_ZONE), MIN_CAP );
/* estimate numH and Hcap */
system->numH = 0;
if( control->hbond_cut > 0 )
for( i = 0; i < system->n; ++i ) {
atom = &(system->my_atoms[i]);
if( system->reax_param.sbp[ atom->type ].p_hbond == 1 )
atom->Hindex = system->numH++;
else atom->Hindex = -1;
}
system->Hcap = (int)(MAX( system->numH * SAFER_ZONE, MIN_CAP ));
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: n=%d local_cap=%d\n",
system->my_rank, system->n, system->local_cap );
fprintf( stderr, "p%d: N=%d total_cap=%d\n",
system->my_rank, system->N, system->total_cap );
fprintf( stderr, "p%d: numH=%d H_cap=%d\n",
system->my_rank, system->numH, system->Hcap );
#endif
return SUCCESS;
}
int Init_Simulation_Data( reax_system *system, control_params *control,
simulation_data *data, char *msg )
{
Reset_Simulation_Data( data, control->virial );
/* initialize the timer(s) */
if( system->my_rank == MASTER_NODE ) {
data->timing.start = Get_Time( );
#if defined(LOG_PERFORMANCE)
Reset_Timing( &data->timing );
#endif
}
//if( !control->restart )
data->step = data->prev_steps = 0;
return SUCCESS;
}
#endif
/************************ initialize workspace ************************/
/* Initialize Taper params */
void Init_Taper( control_params *control, storage *workspace, MPI_Comm comm )
{
real d1, d7;
real swa, swa2, swa3;
real swb, swb2, swb3;
swa = control->nonb_low;
swb = control->nonb_cut;
if( fabs( swa ) > 0.01 )
fprintf( stderr, "Warning: non-zero lower Taper-radius cutoff\n" );
if( swb < 0 ) {
fprintf( stderr, "Negative upper Taper-radius cutoff\n" );
MPI_Abort( comm, INVALID_INPUT );
}
else if( swb < 5 )
fprintf( stderr, "Warning: very low Taper-radius cutoff: %f\n", swb );
d1 = swb - swa;
d7 = pow( d1, 7.0 );
swa2 = SQR( swa );
swa3 = CUBE( swa );
swb2 = SQR( swb );
swb3 = CUBE( swb );
workspace->Tap[7] = 20.0 / d7;
workspace->Tap[6] = -70.0 * (swa + swb) / d7;
workspace->Tap[5] = 84.0 * (swa2 + 3.0*swa*swb + swb2) / d7;
workspace->Tap[4] = -35.0 * (swa3 + 9.0*swa2*swb + 9.0*swa*swb2 + swb3 ) / d7;
workspace->Tap[3] = 140.0 * (swa3*swb + 3.0*swa2*swb2 + swa*swb3 ) / d7;
workspace->Tap[2] =-210.0 * (swa3*swb2 + swa2*swb3) / d7;
workspace->Tap[1] = 140.0 * swa3 * swb3 / d7;
workspace->Tap[0] = (-35.0*swa3*swb2*swb2 + 21.0*swa2*swb3*swb2 +
7.0*swa*swb3*swb3 + swb3*swb3*swb ) / d7;
}
int Init_Workspace( reax_system *system, control_params *control,
storage *workspace, MPI_Comm comm, char *msg )
{
int ret;
ret = Allocate_Workspace( system, control, workspace,
system->local_cap, system->total_cap, comm, msg );
if( ret != SUCCESS )
return ret;
memset( &(workspace->realloc), 0, sizeof(reallocate_data) );
Reset_Workspace( system, workspace );
/* Initialize the Taper function */
Init_Taper( control, workspace, comm );
return SUCCESS;
}
/************** setup communication data structures **************/
int Init_MPI_Datatypes( reax_system *system, storage *workspace,
mpi_datatypes *mpi_data, MPI_Comm comm, char *msg )
{
#if defined(PURE_REAX)
int i, block[11];
MPI_Aint base, disp[11];
MPI_Datatype type[11];
mpi_atom sample;
boundary_atom b_sample;
restart_atom r_sample;
rvec rvec_sample;
rvec2 rvec2_sample;
#endif
/* setup the world */
mpi_data->world = comm;
MPI_Comm_size( comm, &(system->wsize) );
#if defined(PURE_REAX)
/* init mpi buffers */
mpi_data->in1_buffer = NULL;
mpi_data->in2_buffer = NULL;
/* mpi_atom - [orig_id, imprt_id, type, num_bonds, num_hbonds, name,
x, v, f_old, s, t] */
block[0] = block[1] = block[2] = block[3] = block[4] = 1;
block[5] = 8;
block[6] = block[7] = block[8] = 3;
block[9] = block[10] = 4;
MPI_Address( &(sample.orig_id), disp + 0 );
MPI_Address( &(sample.imprt_id), disp + 1 );
MPI_Address( &(sample.type), disp + 2 );
MPI_Address( &(sample.num_bonds), disp + 3 );
MPI_Address( &(sample.num_hbonds), disp + 4 );
MPI_Address( &(sample.name), disp + 5 );
MPI_Address( &(sample.x[0]), disp + 6 );
MPI_Address( &(sample.v[0]), disp + 7 );
MPI_Address( &(sample.f_old[0]), disp + 8 );
MPI_Address( &(sample.s[0]), disp + 9 );
MPI_Address( &(sample.t[0]), disp + 10 );
base = (MPI_Aint)(&(sample));
for( i = 0; i < 11; ++i ) disp[i] -= base;
type[0] = type[1] = type[2] = type[3] = type[4] = MPI_INT;
type[5] = MPI_CHAR;
type[6] = type[7] = type[8] = type[9] = type[10] = MPI_DOUBLE;
MPI_Type_struct( 11, block, disp, type, &(mpi_data->mpi_atom_type) );
MPI_Type_commit( &(mpi_data->mpi_atom_type) );
/* boundary_atom - [orig_id, imprt_id, type, num_bonds, num_hbonds, x] */
block[0] = block[1] = block[2] = block[3] = block[4] = 1;
block[5] = 3;
MPI_Address( &(b_sample.orig_id), disp + 0 );
MPI_Address( &(b_sample.imprt_id), disp + 1 );
MPI_Address( &(b_sample.type), disp + 2 );
MPI_Address( &(b_sample.num_bonds), disp + 3 );
MPI_Address( &(b_sample.num_hbonds), disp + 4 );
MPI_Address( &(b_sample.x[0]), disp + 5 );
base = (MPI_Aint)(&(b_sample));
for( i = 0; i < 6; ++i ) disp[i] -= base;
type[0] = type[1] = type[2] = type[3] = type[4] = MPI_INT;
type[5] = MPI_DOUBLE;
MPI_Type_struct( 6, block, disp, type, &(mpi_data->boundary_atom_type) );
MPI_Type_commit( &(mpi_data->boundary_atom_type) );
/* mpi_rvec */
block[0] = 3;
MPI_Address( &(rvec_sample[0]), disp + 0 );
base = disp[0];
for( i = 0; i < 1; ++i ) disp[i] -= base;
type[0] = MPI_DOUBLE;
MPI_Type_struct( 1, block, disp, type, &(mpi_data->mpi_rvec) );
MPI_Type_commit( &(mpi_data->mpi_rvec) );
/* mpi_rvec2 */
block[0] = 2;
MPI_Address( &(rvec2_sample[0]), disp + 0 );
base = disp[0];
for( i = 0; i < 1; ++i ) disp[i] -= base;
type[0] = MPI_DOUBLE;
MPI_Type_struct( 1, block, disp, type, &(mpi_data->mpi_rvec2) );
MPI_Type_commit( &(mpi_data->mpi_rvec2) );
/* restart_atom - [orig_id, type, name[8], x, v] */
block[0] = block[1] = 1 ;
block[2] = 8;
block[3] = block[4] = 3;
MPI_Address( &(r_sample.orig_id), disp + 0 );
MPI_Address( &(r_sample.type), disp + 1 );
MPI_Address( &(r_sample.name), disp + 2 );
MPI_Address( &(r_sample.x[0]), disp + 3 );
MPI_Address( &(r_sample.v[0]), disp + 4 );
base = (MPI_Aint)(&(r_sample));
for( i = 0; i < 5; ++i ) disp[i] -= base;
type[0] = type[1] = MPI_INT;
type[2] = MPI_CHAR;
type[3] = type[4] = MPI_DOUBLE;
MPI_Type_struct( 5, block, disp, type, &(mpi_data->restart_atom_type) );
MPI_Type_commit( &(mpi_data->restart_atom_type) );
#endif
return SUCCESS;
}
/********************** allocate lists *************************/
#if defined(PURE_REAX)
int Init_Lists( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
mpi_datatypes *mpi_data, char *msg )
{
int i, num_nbrs;
int total_hbonds, total_bonds, bond_cap, num_3body, cap_3body, Htop;
int *hb_top, *bond_top;
MPI_Comm comm;
comm = mpi_data->world;
//for( i = 0; i < MAX_NBRS; ++i ) nrecv[i] = system->my_nbrs[i].est_recv;
//system->N = SendRecv( system, mpi_data, mpi_data->boundary_atom_type, nrecv,
// Sort_Boundary_Atoms, Unpack_Exchange_Message, 1 );
num_nbrs = Estimate_NumNeighbors( system, lists );
if(!Make_List( system->total_cap, num_nbrs, TYP_FAR_NEIGHBOR,
*lists+FAR_NBRS, comm )){
fprintf(stderr, "Problem in initializing far nbrs list. Terminating!\n");
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated far_nbrs: num_far=%d, space=%dMB\n",
system->my_rank, num_nbrs,
(int)(num_nbrs*sizeof(far_neighbor_data)/(1024*1024)) );
#endif
Generate_Neighbor_Lists( system, data, workspace, lists );
bond_top = (int*) calloc( system->total_cap, sizeof(int) );
hb_top = (int*) calloc( system->local_cap, sizeof(int) );
Estimate_Storages( system, control, lists,
&Htop, hb_top, bond_top, &num_3body, comm );
Allocate_Matrix( &(workspace->H), system->local_cap, Htop, comm );
workspace->L = NULL;
workspace->U = NULL;
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated H matrix: Htop=%d, space=%dMB\n",
system->my_rank, Htop,
(int)(Htop * sizeof(sparse_matrix_entry) / (1024*1024)) );
#endif
if( control->hbond_cut > 0 ) {
/* init H indexes */
total_hbonds = 0;
for( i = 0; i < system->n; ++i ) {
system->my_atoms[i].num_hbonds = hb_top[i];
total_hbonds += hb_top[i];
}
total_hbonds = MAX( total_hbonds*SAFER_ZONE, MIN_CAP*MIN_HBONDS );
if( !Make_List( system->Hcap, total_hbonds, TYP_HBOND,
*lists+HBONDS, comm ) ) {
fprintf( stderr, "not enough space for hbonds list. terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated hbonds: total_hbonds=%d, space=%dMB\n",
system->my_rank, total_hbonds,
(int)(total_hbonds*sizeof(hbond_data)/(1024*1024)) );
#endif
}
/* bonds list */
//Allocate_Bond_List( system->N, bond_top, (*lists)+BONDS );
//num_bonds = bond_top[system->N-1];
total_bonds = 0;
for( i = 0; i < system->N; ++i ) {
system->my_atoms[i].num_bonds = bond_top[i];
total_bonds += bond_top[i];
}
bond_cap = MAX( total_bonds*SAFE_ZONE, MIN_CAP*MIN_BONDS );
if( !Make_List( system->total_cap, bond_cap, TYP_BOND,
*lists+BONDS, comm ) ) {
fprintf( stderr, "not enough space for bonds list. terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated bonds: total_bonds=%d, space=%dMB\n",
system->my_rank, bond_cap,
(int)(bond_cap*sizeof(bond_data)/(1024*1024)) );
#endif
/* 3bodies list */
cap_3body = MAX( num_3body*SAFE_ZONE, MIN_3BODIES );
if( !Make_List( bond_cap, cap_3body, TYP_THREE_BODY,
*lists+THREE_BODIES, comm ) ){
fprintf( stderr, "Problem in initializing angles list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated 3-body list: num_3body=%d, space=%dMB\n",
system->my_rank, cap_3body,
(int)(cap_3body*sizeof(three_body_interaction_data)/(1024*1024)) );
#endif
#if defined(TEST_FORCES)
if( !Make_List( system->total_cap, bond_cap*8, TYP_DDELTA,
*lists+DDELTAS, comm ) ) {
fprintf( stderr, "Problem in initializing dDelta list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
fprintf( stderr, "p%d: allocated dDelta list: num_ddelta=%d space=%ldMB\n",
system->my_rank, bond_cap*30,
bond_cap*8*sizeof(dDelta_data)/(1024*1024) );
if( !Make_List( bond_cap, bond_cap*50, TYP_DBO, *lists+DBOS, comm ) ) {
fprintf( stderr, "Problem in initializing dBO list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
fprintf( stderr, "p%d: allocated dbond list: num_dbonds=%d space=%ldMB\n",
system->my_rank, bond_cap*MAX_BONDS*3,
bond_cap*MAX_BONDS*3*sizeof(dbond_data)/(1024*1024) );
#endif
free( hb_top );
free( bond_top );
return SUCCESS;
}
#elif defined(LAMMPS_REAX)
int Init_Lists( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
mpi_datatypes *mpi_data, char *msg )
{
int i, num_nbrs;
int total_hbonds, total_bonds, bond_cap, num_3body, cap_3body, Htop;
int *hb_top, *bond_top;
int nrecv[MAX_NBRS];
MPI_Comm comm;
comm = mpi_data->world;
bond_top = (int*) calloc( system->total_cap, sizeof(int) );
hb_top = (int*) calloc( system->local_cap, sizeof(int) );
Estimate_Storages( system, control, lists,
&Htop, hb_top, bond_top, &num_3body, comm );
if( control->hbond_cut > 0 ) {
/* init H indexes */
total_hbonds = 0;
for( i = 0; i < system->n; ++i ) {
system->my_atoms[i].num_hbonds = hb_top[i];
total_hbonds += hb_top[i];
}
total_hbonds = (int)(MAX( total_hbonds*SAFER_ZONE, MIN_CAP*MIN_HBONDS ));
if( !Make_List( system->Hcap, total_hbonds, TYP_HBOND,
*lists+HBONDS, comm ) ) {
fprintf( stderr, "not enough space for hbonds list. terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated hbonds: total_hbonds=%d, space=%dMB\n",
system->my_rank, total_hbonds,
(int)(total_hbonds*sizeof(hbond_data)/(1024*1024)) );
#endif
}
/* bonds list */
//Allocate_Bond_List( system->N, bond_top, (*lists)+BONDS );
//num_bonds = bond_top[system->N-1];
total_bonds = 0;
for( i = 0; i < system->N; ++i ) {
system->my_atoms[i].num_bonds = bond_top[i];
total_bonds += bond_top[i];
}
bond_cap = (int)(MAX( total_bonds*SAFE_ZONE, MIN_CAP*MIN_BONDS ));
if( !Make_List( system->total_cap, bond_cap, TYP_BOND,
*lists+BONDS, comm ) ) {
fprintf( stderr, "not enough space for bonds list. terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated bonds: total_bonds=%d, space=%dMB\n",
system->my_rank, bond_cap,
(int)(bond_cap*sizeof(bond_data)/(1024*1024)) );
#endif
/* 3bodies list */
cap_3body = (int)(MAX( num_3body*SAFE_ZONE, MIN_3BODIES ));
if( !Make_List( bond_cap, cap_3body, TYP_THREE_BODY,
*lists+THREE_BODIES, comm ) ){
fprintf( stderr, "Problem in initializing angles list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: allocated 3-body list: num_3body=%d, space=%dMB\n",
system->my_rank, cap_3body,
(int)(cap_3body*sizeof(three_body_interaction_data)/(1024*1024)) );
#endif
#if defined(TEST_FORCES)
if( !Make_List( system->total_cap, bond_cap*8, TYP_DDELTA,
*lists+DDELTAS, comm ) ) {
fprintf( stderr, "Problem in initializing dDelta list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
fprintf( stderr, "p%d: allocated dDelta list: num_ddelta=%d space=%ldMB\n",
system->my_rank, bond_cap*30,
bond_cap*8*sizeof(dDelta_data)/(1024*1024) );
if( !Make_List( bond_cap, bond_cap*50, TYP_DBO, (*lists)+DBOS, comm ) ) {
fprintf( stderr, "Problem in initializing dBO list. Terminating!\n" );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
fprintf( stderr, "p%d: allocated dbond list: num_dbonds=%d space=%ldMB\n",
system->my_rank, bond_cap*MAX_BONDS*3,
bond_cap*MAX_BONDS*3*sizeof(dbond_data)/(1024*1024) );
#endif
free( hb_top );
free( bond_top );
return SUCCESS;
}
#endif
#if defined(PURE_REAX)
void Initialize( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
mpi_datatypes *mpi_data )
{
char msg[MAX_STR];
if( Init_MPI_Datatypes( system, workspace, mpi_data, MPI_COMM_WORLD, msg ) ==
FAILURE ) {
fprintf( stderr, "p%d: init_mpi_datatypes: could not create datatypes\n",
system->my_rank );
fprintf( stderr, "p%d: mpi_data couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized mpi datatypes\n", system->my_rank );
#endif
if( Init_System(system, control, data, workspace, mpi_data, msg) == FAILURE ){
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: system could not be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: system initialized\n", system->my_rank );
#endif
if( Init_Simulation_Data(system, control, data, mpi_data, msg) == FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: sim_data couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized simulation data\n", system->my_rank );
#endif
if( Init_Workspace( system, control, workspace, mpi_data->world, msg ) ==
FAILURE ) {
fprintf( stderr, "p%d:init_workspace: not enough memory\n",
system->my_rank );
fprintf( stderr, "p%d:workspace couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized workspace\n", system->my_rank );
#endif
if( Init_Lists( system, control, data, workspace, lists, mpi_data, msg ) ==
FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: system could not be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized lists\n", system->my_rank );
#endif
if(Init_Output_Files(system,control,out_control,mpi_data,msg) == FAILURE) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: could not open output files! terminating...\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: output files opened\n", system->my_rank );
#endif
if( control->tabulate ) {
if( Init_Lookup_Tables(system,control,workspace,mpi_data,msg) == FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: couldn't create lookup table! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized lookup tables\n", system->my_rank );
#endif
}
Init_Force_Functions( control );
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized force functions\n", system->my_rank );
#endif
/*#ifdef TEST_FORCES
Init_Force_Test_Functions();
fprintf(stderr,"p%d: initialized force test functions\n",system->my_rank);
#endif */
}
#elif defined(LAMMPS_REAX)
void Initialize( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control,
mpi_datatypes *mpi_data, MPI_Comm comm )
{
char msg[MAX_STR];
if( Init_MPI_Datatypes(system, workspace, mpi_data, comm, msg) == FAILURE ) {
fprintf( stderr, "p%d: init_mpi_datatypes: could not create datatypes\n",
system->my_rank );
fprintf( stderr, "p%d: mpi_data couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized mpi datatypes\n", system->my_rank );
#endif
if( Init_System(system, control, msg) == FAILURE ){
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: system could not be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: system initialized\n", system->my_rank );
#endif
if( Init_Simulation_Data( system, control, data, msg ) == FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: sim_data couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized simulation data\n", system->my_rank );
#endif
if( Init_Workspace( system, control, workspace, mpi_data->world, msg ) ==
FAILURE ) {
fprintf( stderr, "p%d:init_workspace: not enough memory\n",
system->my_rank );
fprintf( stderr, "p%d:workspace couldn't be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized workspace\n", system->my_rank );
#endif
if( Init_Lists( system, control, data, workspace, lists, mpi_data, msg ) ==
FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: system could not be initialized! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized lists\n", system->my_rank );
#endif
if( Init_Output_Files(system,control,out_control,mpi_data,msg)== FAILURE) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: could not open output files! terminating...\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: output files opened\n", system->my_rank );
#endif
if( control->tabulate ) {
if( Init_Lookup_Tables( system, control, workspace, mpi_data, msg ) == FAILURE ) {
fprintf( stderr, "p%d: %s\n", system->my_rank, msg );
fprintf( stderr, "p%d: couldn't create lookup table! terminating.\n",
system->my_rank );
MPI_Abort( mpi_data->world, CANNOT_INITIALIZE );
}
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized lookup tables\n", system->my_rank );
#endif
}
Init_Force_Functions( control );
#if defined(DEBUG)
fprintf( stderr, "p%d: initialized force functions\n", system->my_rank );
#endif
/*#if defined(TEST_FORCES)
Init_Force_Test_Functions();
fprintf(stderr,"p%d: initialized force test functions\n",system->my_rank);
#endif*/
}
#endif

View File

@ -0,0 +1,35 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __INIT_MD_H_
#define __INIT_MD_H_
#include "reaxc_types.h"
#if defined(PURE_REAX)
void Initialize( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls*, mpi_datatypes* );
#elif defined(LAMMPS_REAX)
void Initialize( reax_system*, control_params*, simulation_data*, storage*,
reax_list**, output_controls*, mpi_datatypes*, MPI_Comm );
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __IO_TOOLS_H_
#define __IO_TOOLS_H_
#include "reaxc_types.h"
int Init_Output_Files( reax_system*, control_params*,
output_controls*, mpi_datatypes*, char* );
int Close_Output_Files( reax_system*, control_params*,
output_controls*, mpi_datatypes* );
void Print_Box( simulation_box*, char*, FILE* );
void Print_Grid( grid*, FILE* );
void Print_GCell_Exchange_Bounds( int, neighbor_proc* );
void Print_Native_GCells( reax_system* );
void Print_All_GCells( reax_system*);
void Print_Init_Atoms( reax_system*, storage* );
void Print_My_Atoms( reax_system* );
void Print_My_Ext_Atoms( reax_system* );
void Print_Far_Neighbors( reax_system*, reax_list**, control_params *);
void Print_Sparse_Matrix( reax_system*, sparse_matrix* );
void Print_Sparse_Matrix2( reax_system*, sparse_matrix*, char* );
void Print_Linear_System( reax_system*, control_params*, storage*, int );
void Print_LinSys_Soln( reax_system*, real*, real*, real* );
void Print_Charges( reax_system* );
void Print_Bonds( reax_system*, reax_list*, char* );
void Print_Bond_List2( reax_system*, reax_list*, char* );
void Print_Total_Force( reax_system*, simulation_data*, storage* );
void Output_Results( reax_system*, control_params*, simulation_data*,
reax_list**, output_controls*, mpi_datatypes* );
#if defined(DEBUG_FOCUS) || defined(TEST_FORCES) || defined(TEST_ENERGY)
void Debug_Marker_Bonded( output_controls*, int );
void Debug_Marker_Nonbonded( output_controls*, int );
void Print_Near_Neighbors_List( reax_system*, reax_list**, control_params*,
simulation_data*, output_controls* );
void Print_Far_Neighbors_List( reax_system*, reax_list**, control_params*,
simulation_data*, output_controls* );
void Print_Bond_List( reax_system*, control_params*, simulation_data*,
reax_list**, output_controls* );
/*void Dummy_Printer( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_Bond_Orders( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_Bond_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_LonePair_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_OverUnderCoor_Forces( reax_system*, control_params*,
simulation_data*, storage*, reax_list**,
output_controls* );
void Print_Three_Body_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_Hydrogen_Bond_Forces( reax_system*, control_params*,
simulation_data*, storage*, reax_list**,
output_controls* );
void Print_Four_Body_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Print_vdW_Coulomb_Forces( reax_system*, control_params*,
simulation_data*, storage*, reax_list**,
output_controls* );
void Print_Total_Force( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Compare_Total_Forces( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );*/
//void Print_Total_Force( reax_system*, control_params* );
void Print_Force_Files( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls*,
mpi_datatypes * );
//void Init_Force_Test_Functions( );
int fn_qsort_intcmp( const void *, const void * );
void Print_Far_Neighbors_List( reax_system*, reax_list**, control_params*,
simulation_data*, output_controls* );
void Print_Near_Neighbors_List( reax_system*, reax_list**, control_params*,
simulation_data*, output_controls* );
void Print_Bond_List( reax_system*, control_params*, simulation_data*,
reax_list**, output_controls*);
#endif
#endif

View File

@ -0,0 +1,157 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "list.h"
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_list.h"
#include "reaxc_tool_box.h"
#endif
/************* allocate list space ******************/
int Make_List(int n, int num_intrs, int type, reax_list *l, MPI_Comm comm)
{
l->allocated = 1;
l->n = n;
l->num_intrs = num_intrs;
l->index = (int*) smalloc( n * sizeof(int), "list:index", comm );
l->end_index = (int*) smalloc( n * sizeof(int), "list:end_index", comm );
l->type = type;
#if defined(DEBUG_FOCUS)
fprintf( stderr, "list: n=%d num_intrs=%d type=%d\n", n, num_intrs, type );
#endif
switch(l->type) {
case TYP_VOID:
l->select.v = (void*) smalloc(l->num_intrs * sizeof(void*), "list:v", comm);
break;
case TYP_THREE_BODY:
l->select.three_body_list = (three_body_interaction_data*)
smalloc( l->num_intrs * sizeof(three_body_interaction_data),
"list:three_bodies", comm );
break;
case TYP_BOND:
l->select.bond_list = (bond_data*)
smalloc( l->num_intrs * sizeof(bond_data), "list:bonds", comm );
break;
case TYP_DBO:
l->select.dbo_list = (dbond_data*)
smalloc( l->num_intrs * sizeof(dbond_data), "list:dbonds", comm );
break;
case TYP_DDELTA:
l->select.dDelta_list = (dDelta_data*)
smalloc( l->num_intrs * sizeof(dDelta_data), "list:dDeltas", comm );
break;
case TYP_FAR_NEIGHBOR:
l->select.far_nbr_list = (far_neighbor_data*)
smalloc(l->num_intrs * sizeof(far_neighbor_data), "list:far_nbrs", comm);
break;
case TYP_HBOND:
l->select.hbond_list = (hbond_data*)
smalloc( l->num_intrs * sizeof(hbond_data), "list:hbonds", comm );
break;
default:
fprintf( stderr, "ERROR: no %d list type defined!\n", l->type );
MPI_Abort( comm, INVALID_INPUT );
}
return SUCCESS;
}
void Delete_List( reax_list *l, MPI_Comm comm )
{
if( l->allocated == 0 )
return;
l->allocated = 0;
sfree( l->index, "list:index" );
sfree( l->end_index, "list:end_index" );
switch(l->type) {
case TYP_VOID:
sfree( l->select.v, "list:v" );
break;
case TYP_HBOND:
sfree( l->select.hbond_list, "list:hbonds" );
break;
case TYP_FAR_NEIGHBOR:
sfree( l->select.far_nbr_list, "list:far_nbrs" );
break;
case TYP_BOND:
sfree( l->select.bond_list, "list:bonds" );
break;
case TYP_DBO:
sfree( l->select.dbo_list, "list:dbos" );
break;
case TYP_DDELTA:
sfree( l->select.dDelta_list, "list:dDeltas" );
break;
case TYP_THREE_BODY:
sfree( l->select.three_body_list, "list:three_bodies" );
break;
default:
fprintf( stderr, "ERROR: no %d list type defined!\n", l->type );
MPI_Abort( comm, INVALID_INPUT );
}
}
#if defined(PURE_REAX)
inline int Num_Entries( int i, reax_list *l )
{
return l->end_index[i] - l->index[i];
}
inline int Start_Index( int i, reax_list *l )
{
return l->index[i];
}
inline int End_Index( int i, reax_list *l )
{
return l->end_index[i];
}
inline void Set_Start_Index( int i, int val, reax_list *l )
{
l->index[i] = val;
}
inline void Set_End_Index( int i, int val, reax_list *l )
{
l->end_index[i] = val;
}
#endif

View File

@ -0,0 +1,63 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __LIST_H_
#define __LIST_H_
#include "reaxc_types.h"
int Make_List( int, int, int, reax_list*, MPI_Comm );
void Delete_List( reax_list*, MPI_Comm );
inline int Num_Entries(int,reax_list*);
inline int Start_Index( int, reax_list* );
inline int End_Index( int, reax_list* );
inline void Set_Start_Index(int,int,reax_list*);
inline void Set_End_Index(int,int,reax_list*);
#if defined(LAMMPS_REAX)
inline int Num_Entries( int i, reax_list *l )
{
return l->end_index[i] - l->index[i];
}
inline int Start_Index( int i, reax_list *l )
{
return l->index[i];
}
inline int End_Index( int i, reax_list *l )
{
return l->end_index[i];
}
inline void Set_Start_Index( int i, int val, reax_list *l )
{
l->index[i] = val;
}
inline void Set_End_Index( int i, int val, reax_list *l )
{
l->end_index[i] = val;
}
#endif // LAMMPS_REAX
#endif

View File

@ -0,0 +1,339 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "lookup.h"
#include "nonbonded.h"
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_lookup.h"
#include "reaxc_nonbonded.h"
#include "reaxc_tool_box.h"
#endif
LR_lookup_table **LR;
/* Fills solution into x. Warning: will modify c and d! */
void Tridiagonal_Solve( const real *a, const real *b,
real *c, real *d, real *x, unsigned int n){
int i;
real id;
/* Modify the coefficients. */
c[0] /= b[0]; /* Division by zero risk. */
d[0] /= b[0]; /* Division by zero would imply a singular matrix. */
for(i = 1; i < n; i++){
id = (b[i] - c[i-1] * a[i]); /* Division by zero risk. */
c[i] /= id; /* Last value calculated is redundant. */
d[i] = (d[i] - d[i-1] * a[i])/id;
}
/* Now back substitute. */
x[n - 1] = d[n - 1];
for(i = n - 2; i >= 0; i--)
x[i] = d[i] - c[i] * x[i + 1];
}
void Natural_Cubic_Spline( const real *h, const real *f,
cubic_spline_coef *coef, unsigned int n,
MPI_Comm comm )
{
int i;
real *a, *b, *c, *d, *v;
/* allocate space for the linear system */
a = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
b = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
c = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
d = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
v = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
/* build the linear system */
a[0] = a[1] = a[n-1] = 0;
for( i = 2; i < n-1; ++i )
a[i] = h[i-1];
b[0] = b[n-1] = 0;
for( i = 1; i < n-1; ++i )
b[i] = 2 * (h[i-1] + h[i]);
c[0] = c[n-2] = c[n-1] = 0;
for( i = 1; i < n-2; ++i )
c[i] = h[i];
d[0] = d[n-1] = 0;
for( i = 1; i < n-1; ++i )
d[i] = 6 * ((f[i+1]-f[i])/h[i] - (f[i]-f[i-1])/h[i-1]);
v[0] = 0;
v[n-1] = 0;
Tridiagonal_Solve( &(a[1]), &(b[1]), &(c[1]), &(d[1]), &(v[1]), n-2 );
for( i = 1; i < n; ++i ){
coef[i-1].d = (v[i] - v[i-1]) / (6*h[i-1]);
coef[i-1].c = v[i]/2;
coef[i-1].b = (f[i]-f[i-1])/h[i-1] + h[i-1]*(2*v[i] + v[i-1])/6;
coef[i-1].a = f[i];
}
sfree( a, "cubic_spline:a" );
sfree( b, "cubic_spline:b" );
sfree( c, "cubic_spline:c" );
sfree( d, "cubic_spline:d" );
sfree( v, "cubic_spline:v" );
}
void Complete_Cubic_Spline( const real *h, const real *f, real v0, real vlast,
cubic_spline_coef *coef, unsigned int n,
MPI_Comm comm )
{
int i;
real *a, *b, *c, *d, *v;
/* allocate space for the linear system */
a = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
b = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
c = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
d = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
v = (real*) smalloc( n * sizeof(real), "cubic_spline:a", comm );
/* build the linear system */
a[0] = 0;
for( i = 1; i < n; ++i )
a[i] = h[i-1];
b[0] = 2*h[0];
for( i = 1; i < n; ++i )
b[i] = 2 * (h[i-1] + h[i]);
c[n-1] = 0;
for( i = 0; i < n-1; ++i )
c[i] = h[i];
d[0] = 6 * (f[1]-f[0])/h[0] - 6 * v0;
d[n-1] = 6 * vlast - 6 * (f[n-1]-f[n-2]/h[n-2]);
for( i = 1; i < n-1; ++i )
d[i] = 6 * ((f[i+1]-f[i])/h[i] - (f[i]-f[i-1])/h[i-1]);
Tridiagonal_Solve( &(a[0]), &(b[0]), &(c[0]), &(d[0]), &(v[0]), n );
for( i = 1; i < n; ++i ){
coef[i-1].d = (v[i] - v[i-1]) / (6*h[i-1]);
coef[i-1].c = v[i]/2;
coef[i-1].b = (f[i]-f[i-1])/h[i-1] + h[i-1]*(2*v[i] + v[i-1])/6;
coef[i-1].a = f[i];
}
sfree( a, "cubic_spline:a" );
sfree( b, "cubic_spline:b" );
sfree( c, "cubic_spline:c" );
sfree( d, "cubic_spline:d" );
sfree( v, "cubic_spline:v" );
}
void LR_Lookup( LR_lookup_table *t, real r, LR_data *y )
{
int i;
real base, dif;
i = (int)(r * t->inv_dx);
if( i == 0 ) ++i;
base = (real)(i+1) * t->dx;
dif = r - base;
y->e_vdW = ((t->vdW[i].d*dif + t->vdW[i].c)*dif + t->vdW[i].b)*dif +
t->vdW[i].a;
y->CEvd = ((t->CEvd[i].d*dif + t->CEvd[i].c)*dif +
t->CEvd[i].b)*dif + t->CEvd[i].a;
y->e_ele = ((t->ele[i].d*dif + t->ele[i].c)*dif + t->ele[i].b)*dif +
t->ele[i].a;
y->CEclmb = ((t->CEclmb[i].d*dif + t->CEclmb[i].c)*dif + t->CEclmb[i].b)*dif +
t->CEclmb[i].a;
y->H = y->e_ele * EV_to_KCALpMOL / C_ele;
}
int Init_Lookup_Tables( reax_system *system, control_params *control,
storage *workspace, mpi_datatypes *mpi_data, char *msg )
{
int i, j, r;
int num_atom_types;
int existing_types[MAX_ATOM_TYPES], aggregated[MAX_ATOM_TYPES];
real dr;
real *h, *fh, *fvdw, *fele, *fCEvd, *fCEclmb;
real v0_vdw, v0_ele, vlast_vdw, vlast_ele;
MPI_Comm comm;
/* initializations */
v0_vdw = 0;
v0_ele = 0;
vlast_vdw = 0;
vlast_ele = 0;
comm = mpi_data->world;
num_atom_types = system->reax_param.num_atom_types;
dr = control->nonb_cut / control->tabulate;
h = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:h", comm );
fh = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:fh", comm );
fvdw = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:fvdw", comm );
fCEvd = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:fCEvd", comm );
fele = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:fele", comm );
fCEclmb = (real*)
smalloc( (control->tabulate+2) * sizeof(real), "lookup:fCEclmb", comm );
/* allocate Long-Range LookUp Table space based on
number of atom types in the ffield file */
LR = (LR_lookup_table**)
scalloc( num_atom_types, sizeof(LR_lookup_table*), "lookup:LR", comm );
for( i = 0; i < num_atom_types; ++i )
LR[i] = (LR_lookup_table*)
scalloc( num_atom_types, sizeof(LR_lookup_table), "lookup:LR[i]", comm );
/* most atom types in ffield file will not exist in the current
simulation. to avoid unnecessary lookup table space, determine
the atom types that exist in the current simulation */
for( i = 0; i < MAX_ATOM_TYPES; ++i )
existing_types[i] = 0;
for( i = 0; i < system->n; ++i )
existing_types[ system->my_atoms[i].type ] = 1;
MPI_Allreduce( existing_types, aggregated, MAX_ATOM_TYPES,
MPI_INT, MPI_SUM, mpi_data->world );
/* fill in the lookup table entries for existing atom types.
only lower half should be enough. */
for( i = 0; i < num_atom_types; ++i )
if( aggregated[i] )
//for( j = 0; j < num_atom_types; ++j )
for( j = i; j < num_atom_types; ++j )
if( aggregated[j] ) {
LR[i][j].xmin = 0;
LR[i][j].xmax = control->nonb_cut;
LR[i][j].n = control->tabulate + 2;
LR[i][j].dx = dr;
LR[i][j].inv_dx = control->tabulate / control->nonb_cut;
LR[i][j].y = (LR_data*)
smalloc( LR[i][j].n * sizeof(LR_data), "lookup:LR[i,j].y", comm );
LR[i][j].H = (cubic_spline_coef*)
smalloc( LR[i][j].n*sizeof(cubic_spline_coef),"lookup:LR[i,j].H" ,
comm );
LR[i][j].vdW = (cubic_spline_coef*)
smalloc( LR[i][j].n*sizeof(cubic_spline_coef),"lookup:LR[i,j].vdW",
comm);
LR[i][j].CEvd = (cubic_spline_coef*)
smalloc( LR[i][j].n*sizeof(cubic_spline_coef),"lookup:LR[i,j].CEvd",
comm);
LR[i][j].ele = (cubic_spline_coef*)
smalloc( LR[i][j].n*sizeof(cubic_spline_coef),"lookup:LR[i,j].ele",
comm );
LR[i][j].CEclmb = (cubic_spline_coef*)
smalloc( LR[i][j].n*sizeof(cubic_spline_coef),
"lookup:LR[i,j].CEclmb", comm );
for( r = 1; r <= control->tabulate; ++r ) {
LR_vdW_Coulomb( system, workspace, i, j, r * dr, &(LR[i][j].y[r]) );
h[r] = LR[i][j].dx;
fh[r] = LR[i][j].y[r].H;
fvdw[r] = LR[i][j].y[r].e_vdW;
fCEvd[r] = LR[i][j].y[r].CEvd;
fele[r] = LR[i][j].y[r].e_ele;
fCEclmb[r] = LR[i][j].y[r].CEclmb;
}
// init the start-end points
h[r] = LR[i][j].dx;
v0_vdw = LR[i][j].y[1].CEvd;
v0_ele = LR[i][j].y[1].CEclmb;
fh[r] = fh[r-1];
fvdw[r] = fvdw[r-1];
fCEvd[r] = fCEvd[r-1];
fele[r] = fele[r-1];
fCEclmb[r] = fCEclmb[r-1];
vlast_vdw = fCEvd[r-1];
vlast_ele = fele[r-1];
Natural_Cubic_Spline( &h[1], &fh[1],
&(LR[i][j].H[1]), control->tabulate+1, comm );
Complete_Cubic_Spline( &h[1], &fvdw[1], v0_vdw, vlast_vdw,
&(LR[i][j].vdW[1]), control->tabulate+1,
comm );
Natural_Cubic_Spline( &h[1], &fCEvd[1],
&(LR[i][j].CEvd[1]), control->tabulate+1,
comm );
Complete_Cubic_Spline( &h[1], &fele[1], v0_ele, vlast_ele,
&(LR[i][j].ele[1]), control->tabulate+1,
comm );
Natural_Cubic_Spline( &h[1], &fCEclmb[1],
&(LR[i][j].CEclmb[1]), control->tabulate+1,
comm );
}
else{
LR[i][j].n = 0;
}
free(h);
free(fh);
free(fvdw);
free(fCEvd);
free(fele);
free(fCEclmb);
return 1;
}
void Deallocate_Lookup_Tables( reax_system *system )
{
int i, j;
int ntypes;
ntypes = system->reax_param.num_atom_types;
for( i = 0; i < ntypes; ++i ) {
for( j = i; j < ntypes; ++j )
if( LR[i][j].n ) {
sfree( LR[i][j].y, "LR[i,j].y" );
sfree( LR[i][j].H, "LR[i,j].H" );
sfree( LR[i][j].vdW, "LR[i,j].vdW" );
sfree( LR[i][j].CEvd, "LR[i,j].CEvd" );
sfree( LR[i][j].ele, "LR[i,j].ele" );
sfree( LR[i][j].CEclmb, "LR[i,j].CEclmb" );
}
sfree( LR[i], "LR[i]" );
}
sfree( LR, "LR" );
}

View File

@ -0,0 +1,32 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __LOOKUP_H_
#define __LOOKUP_H_
#include "reaxc_types.h"
int Init_Lookup_Tables( reax_system*, control_params*, storage*,
mpi_datatypes*, char* );
void Deallocate_Lookup_Tables( reax_system* );
#endif

View File

@ -0,0 +1,311 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "multi_body.h"
#include "bond_orders.h"
#include "list.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_multi_body.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_vector.h"
#endif
void Atom_Energy( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
output_controls *out_control )
{
int i, j, pj, type_i, type_j;
real Delta_lpcorr, dfvl;
real e_lp, expvd2, inv_expvd2, dElp, CElp, DlpVi;
real e_lph, Di, vov3, deahu2dbo, deahu2dsbo;
real e_ov, CEover1, CEover2, CEover3, CEover4;
real exp_ovun1, exp_ovun2, sum_ovun1, sum_ovun2;
real exp_ovun2n, exp_ovun6, exp_ovun8;
real inv_exp_ovun1, inv_exp_ovun2, inv_exp_ovun2n, inv_exp_ovun8;
real e_un, CEunder1, CEunder2, CEunder3, CEunder4;
real p_lp1, p_lp2, p_lp3;
real p_ovun2, p_ovun3, p_ovun4, p_ovun5, p_ovun6, p_ovun7, p_ovun8;
single_body_parameters *sbp_i, *sbp_j;
two_body_parameters *twbp;
bond_data *pbond;
bond_order_data *bo_ij;
reax_list *bonds = (*lists) + BONDS;
/* Initialize parameters */
p_lp1 = system->reax_param.gp.l[15];
p_lp3 = system->reax_param.gp.l[5];
p_ovun3 = system->reax_param.gp.l[32];
p_ovun4 = system->reax_param.gp.l[31];
p_ovun6 = system->reax_param.gp.l[6];
p_ovun7 = system->reax_param.gp.l[8];
p_ovun8 = system->reax_param.gp.l[9];
for( i = 0; i < system->n; ++i ) {
/* set the parameter pointer */
type_i = system->my_atoms[i].type;
sbp_i = &(system->reax_param.sbp[ type_i ]);
/* lone-pair Energy */
p_lp2 = sbp_i->p_lp2;
expvd2 = exp( -75 * workspace->Delta_lp[i] );
inv_expvd2 = 1. / (1. + expvd2 );
/* calculate the energy */
data->my_en.e_lp += e_lp =
p_lp2 * workspace->Delta_lp[i] * inv_expvd2;
dElp = p_lp2 * inv_expvd2 +
75 * p_lp2 * workspace->Delta_lp[i] * expvd2 * SQR(inv_expvd2);
CElp = dElp * workspace->dDelta_lp[i];
workspace->CdDelta[i] += CElp; // lp - 1st term
#ifdef TEST_ENERGY
// fprintf( out_control->elp, "%24.15e%24.15e%24.15e%24.15e\n",
// p_lp2, workspace->Delta_lp_temp[i], expvd2, dElp );
// fprintf( out_control->elp, "%6d%24.15e%24.15e%24.15e\n",
fprintf( out_control->elp, "%6d%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, workspace->nlp[i],
e_lp, data->my_en.e_lp );
#endif
#ifdef TEST_FORCES
Add_dDelta( system, lists, i, CElp, workspace->f_lp ); // lp - 1st term
#endif
/* correction for C2 */
if( system->reax_param.gp.l[5] > 0.001 &&
!strcmp( system->reax_param.sbp[type_i].name, "C" ) )
for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj )
if( system->my_atoms[i].orig_id <
system->my_atoms[bonds->select.bond_list[pj].nbr].orig_id ) {
j = bonds->select.bond_list[pj].nbr;
type_j = system->my_atoms[j].type;
if( !strcmp( system->reax_param.sbp[type_j].name, "C" ) ) {
twbp = &( system->reax_param.tbp[type_i][type_j]);
bo_ij = &( bonds->select.bond_list[pj].bo_data );
Di = workspace->Delta[i];
vov3 = bo_ij->BO - Di - 0.040*pow(Di, 4.);
if( vov3 > 3. ) {
data->my_en.e_lp += e_lph = p_lp3 * SQR(vov3-3.0);
deahu2dbo = 2.*p_lp3*(vov3 - 3.);
deahu2dsbo = 2.*p_lp3*(vov3 - 3.)*(-1. - 0.16*pow(Di, 3.));
bo_ij->Cdbo += deahu2dbo;
workspace->CdDelta[i] += deahu2dsbo;
#ifdef TEST_ENERGY
fprintf(out_control->elp,"C2cor%6d%6d%12.6f%12.6f%12.6f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
e_lph, deahu2dbo, deahu2dsbo );
#endif
#ifdef TEST_FORCES
Add_dBO(system, lists, i, pj, deahu2dbo, workspace->f_lp);
Add_dDelta(system, lists, i, deahu2dsbo, workspace->f_lp);
#endif
}
}
}
}
for( i = 0; i < system->n; ++i ) {
type_i = system->my_atoms[i].type;
sbp_i = &(system->reax_param.sbp[ type_i ]);
/* over-coordination energy */
if( sbp_i->mass > 21.0 )
dfvl = 0.0;
else dfvl = 1.0; // only for 1st-row elements
p_ovun2 = sbp_i->p_ovun2;
sum_ovun1 = sum_ovun2 = 0;
for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) {
j = bonds->select.bond_list[pj].nbr;
type_j = system->my_atoms[j].type;
bo_ij = &(bonds->select.bond_list[pj].bo_data);
sbp_j = &(system->reax_param.sbp[ type_j ]);
twbp = &(system->reax_param.tbp[ type_i ][ type_j ]);
sum_ovun1 += twbp->p_ovun1 * twbp->De_s * bo_ij->BO;
sum_ovun2 += (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j])*
( bo_ij->BO_pi + bo_ij->BO_pi2 );
/*fprintf( stdout, "%4d%4d%12.6f%12.6f%12.6f\n",
i+1, j+1,
dfvl * workspace->Delta_lp_temp[j],
sbp_j->nlp_opt,
workspace->nlp_temp[j] );*/
}
exp_ovun1 = p_ovun3 * exp( p_ovun4 * sum_ovun2 );
inv_exp_ovun1 = 1.0 / (1 + exp_ovun1);
Delta_lpcorr = workspace->Delta[i] -
(dfvl * workspace->Delta_lp_temp[i]) * inv_exp_ovun1;
exp_ovun2 = exp( p_ovun2 * Delta_lpcorr );
inv_exp_ovun2 = 1.0 / (1.0 + exp_ovun2);
DlpVi = 1.0 / (Delta_lpcorr + sbp_i->valency + 1e-8);
CEover1 = Delta_lpcorr * DlpVi * inv_exp_ovun2;
data->my_en.e_ov += e_ov = sum_ovun1 * CEover1;
CEover2 = sum_ovun1 * DlpVi * inv_exp_ovun2 *
(1.0 - Delta_lpcorr * ( DlpVi + p_ovun2 * exp_ovun2 * inv_exp_ovun2 ));
CEover3 = CEover2 * (1.0 - dfvl * workspace->dDelta_lp[i] * inv_exp_ovun1 );
CEover4 = CEover2 * (dfvl * workspace->Delta_lp_temp[i]) *
p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1);
/* under-coordination potential */
p_ovun2 = sbp_i->p_ovun2;
p_ovun5 = sbp_i->p_ovun5;
exp_ovun2n = 1.0 / exp_ovun2;
exp_ovun6 = exp( p_ovun6 * Delta_lpcorr );
exp_ovun8 = p_ovun7 * exp(p_ovun8 * sum_ovun2);
inv_exp_ovun2n = 1.0 / (1.0 + exp_ovun2n);
inv_exp_ovun8 = 1.0 / (1.0 + exp_ovun8);
data->my_en.e_un += e_un =
-p_ovun5 * (1.0 - exp_ovun6) * inv_exp_ovun2n * inv_exp_ovun8;
CEunder1 = inv_exp_ovun2n *
( p_ovun5 * p_ovun6 * exp_ovun6 * inv_exp_ovun8 +
p_ovun2 * e_un * exp_ovun2n );
CEunder2 = -e_un * p_ovun8 * exp_ovun8 * inv_exp_ovun8;
CEunder3 = CEunder1 * (1.0 - dfvl*workspace->dDelta_lp[i]*inv_exp_ovun1);
CEunder4 = CEunder1 * (dfvl*workspace->Delta_lp_temp[i]) *
p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1) + CEunder2;
/* forces */
workspace->CdDelta[i] += CEover3; // OvCoor - 2nd term
workspace->CdDelta[i] += CEunder3; // UnCoor - 1st term
#ifdef TEST_FORCES
Add_dDelta( system, lists, i, CEover3, workspace->f_ov ); // OvCoor 2nd
Add_dDelta( system, lists, i, CEunder3, workspace->f_un ); // UnCoor 1st
#endif
for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) {
pbond = &(bonds->select.bond_list[pj]);
j = pbond->nbr;
bo_ij = &(pbond->bo_data);
twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ]
[system->my_atoms[pbond->nbr].type]);
bo_ij->Cdbo += CEover1 * twbp->p_ovun1 * twbp->De_s;// OvCoor-1st
workspace->CdDelta[j] += CEover4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
(bo_ij->BO_pi + bo_ij->BO_pi2); // OvCoor-3a
bo_ij->Cdbopi += CEover4 *
(workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // OvCoor-3b
bo_ij->Cdbopi2 += CEover4 *
(workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // OvCoor-3b
workspace->CdDelta[j] += CEunder4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
(bo_ij->BO_pi + bo_ij->BO_pi2); // UnCoor - 2a
bo_ij->Cdbopi += CEunder4 *
(workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // UnCoor-2b
bo_ij->Cdbopi2 += CEunder4 *
(workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // UnCoor-2b
#ifdef TEST_ENERGY
/* fprintf( out_control->eov, "%6d%12.6f\n",
workspace->reverse_map[j],
// CEover1 * twbp->p_ovun1 * twbp->De_s, CEover3,
CEover4 * (1.0 - workspace->dDelta_lp[j]) *
(bo_ij->BO_pi + bo_ij->BO_pi2)
*/// /*CEover4 * (workspace->Delta[j]-workspace->Delta_lp[j])*/);
// fprintf( out_control->eov, "%6d%12.6f\n",
// fprintf( out_control->eov, "%6d%24.15e\n",
// system->my_atoms[j].orig_id,
// CEover1 * twbp->p_ovun1 * twbp->De_s, CEover3,
// CEover4 * (1.0 - workspace->dDelta_lp[j]) *
// (bo_ij->BO_pi + bo_ij->BO_pi2)
// /*CEover4 * (workspace->Delta[j]-workspace->Delta_lp[j])*/);
// CEunder4 * (1.0 - workspace->dDelta_lp[j]) *
// (bo_ij->BO_pi + bo_ij->BO_pi2),
// CEunder4 * (workspace->Delta[j] - workspace->Delta_lp[j]) );
#endif
#ifdef TEST_FORCES
Add_dBO( system, lists, i, pj, CEover1 * twbp->p_ovun1 * twbp->De_s,
workspace->f_ov ); // OvCoor - 1st term
Add_dDelta( system, lists, j,
CEover4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
(bo_ij->BO_pi + bo_ij->BO_pi2),
workspace->f_ov ); // OvCoor - 3a
Add_dBOpinpi2( system, lists, i, pj,
CEover4 * (workspace->Delta[j] -
dfvl * workspace->Delta_lp_temp[j]),
CEover4 * (workspace->Delta[j] -
dfvl * workspace->Delta_lp_temp[j]),
workspace->f_ov, workspace->f_ov ); // OvCoor - 3b
Add_dDelta( system, lists, j,
CEunder4 * (1.0 - dfvl*workspace->dDelta_lp[j]) *
(bo_ij->BO_pi + bo_ij->BO_pi2),
workspace->f_un ); // UnCoor - 2a
Add_dBOpinpi2( system, lists, i, pj,
CEunder4 * (workspace->Delta[j] -
dfvl * workspace->Delta_lp_temp[j]),
CEunder4 * (workspace->Delta[j] -
dfvl * workspace->Delta_lp_temp[j]),
workspace->f_un, workspace->f_un ); // UnCoor - 2b
#endif
}
#ifdef TEST_ENERGY
//fprintf( out_control->elp, "%6d%24.15e%24.15e%24.15e\n",
//fprintf( out_control->elp, "%6d%12.4f%12.4f%12.4f\n",
// system->my_atoms[i].orig_id, workspace->nlp[i],
// e_lp, data->my_en.e_lp );
//fprintf( out_control->eov, "%6d%24.15e%24.15e\n",
fprintf( out_control->eov, "%6d%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
e_ov, data->my_en.e_ov + data->my_en.e_un );
//fprintf( out_control->eun, "%6d%24.15e%24.15e\n",
fprintf( out_control->eun, "%6d%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
e_un, data->my_en.e_ov + data->my_en.e_un );
#endif
}
}

View File

@ -0,0 +1,31 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __MULTI_BODY_H_
#define __MULTI_BODY_H_
#include "reaxc_types.h"
void Atom_Energy( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
#endif

View File

@ -0,0 +1,424 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "nonbonded.h"
#include "bond_orders.h"
#include "list.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_nonbonded.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_vector.h"
#endif
void vdW_Coulomb_Energy( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control )
{
int i, j, pj, natoms;
int start_i, end_i, orig_i, orig_j;
real p_vdW1, p_vdW1i;
real powr_vdW1, powgi_vdW1;
real tmp, r_ij, fn13, exp1, exp2;
real Tap, dTap, dfn13, CEvd, CEclmb, de_core;
real dr3gamij_1, dr3gamij_3;
real e_ele, e_vdW, e_core;
rvec temp, ext_press;
two_body_parameters *twbp;
far_neighbor_data *nbr_pj;
reax_list *far_nbrs;
// rtensor temp_rtensor, total_rtensor;
natoms = system->n;
far_nbrs = (*lists) + FAR_NBRS;
p_vdW1 = system->reax_param.gp.l[28];
p_vdW1i = 1.0 / p_vdW1;
e_core = 0;
e_vdW = 0;
for( i = 0; i < natoms; ++i ) {
start_i = Start_Index(i, far_nbrs);
end_i = End_Index(i, far_nbrs);
orig_i = system->my_atoms[i].orig_id;
//fprintf( stderr, "i:%d, start_i: %d, end_i: %d\n", i, start_i, end_i );
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
j = nbr_pj->nbr;
orig_j = system->my_atoms[j].orig_id;
if( nbr_pj->d <= control->nonb_cut && (j < natoms || orig_i < orig_j) ) {
r_ij = nbr_pj->d;
twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ]
[ system->my_atoms[j].type ]);
/* Calculate Taper and its derivative */
// Tap = nbr_pj->Tap; -- precomputed during compte_H
Tap = workspace->Tap[7] * r_ij + workspace->Tap[6];
Tap = Tap * r_ij + workspace->Tap[5];
Tap = Tap * r_ij + workspace->Tap[4];
Tap = Tap * r_ij + workspace->Tap[3];
Tap = Tap * r_ij + workspace->Tap[2];
Tap = Tap * r_ij + workspace->Tap[1];
Tap = Tap * r_ij + workspace->Tap[0];
dTap = 7*workspace->Tap[7] * r_ij + 6*workspace->Tap[6];
dTap = dTap * r_ij + 5*workspace->Tap[5];
dTap = dTap * r_ij + 4*workspace->Tap[4];
dTap = dTap * r_ij + 3*workspace->Tap[3];
dTap = dTap * r_ij + 2*workspace->Tap[2];
dTap += workspace->Tap[1]/r_ij;
/*vdWaals Calculations*/
if(system->reax_param.gp.vdw_type==1 || system->reax_param.gp.vdw_type==3)
{ // shielding
powr_vdW1 = pow(r_ij, p_vdW1);
powgi_vdW1 = pow( 1.0 / twbp->gamma_w, p_vdW1);
fn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i );
exp1 = exp( twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
exp2 = exp( 0.5 * twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
e_vdW = twbp->D * (exp1 - 2.0 * exp2);
data->my_en.e_vdW += Tap * e_vdW;
dfn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i - 1.0) *
pow(r_ij, p_vdW1 - 2.0);
CEvd = dTap * e_vdW -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
}
else{ // no shielding
exp1 = exp( twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
exp2 = exp( 0.5 * twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
e_vdW = twbp->D * (exp1 - 2.0 * exp2);
data->my_en.e_vdW += Tap * e_vdW;
CEvd = dTap * e_vdW -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2);
}
if(system->reax_param.gp.vdw_type==2 || system->reax_param.gp.vdw_type==3)
{ // innner wall
e_core = twbp->ecore * exp(twbp->acore * (1.0-(r_ij/twbp->rcore)));
data->my_en.e_vdW += Tap * e_core;
de_core = -(twbp->acore/twbp->rcore) * e_core;
CEvd += dTap * e_core + Tap * de_core;
}
/*Coulomb Calculations*/
dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 );
tmp = Tap / dr3gamij_3;
data->my_en.e_ele += e_ele =
C_ele * system->my_atoms[i].q * system->my_atoms[j].q * tmp;
CEclmb = C_ele * system->my_atoms[i].q * system->my_atoms[j].q *
( dTap - Tap * r_ij / dr3gamij_1 ) / dr3gamij_3;
// fprintf( fout, "%5d %5d %10.6f %10.6f\n",
// MIN( system->my_atoms[i].orig_id, system->my_atoms[j].orig_id ),
// MAX( system->my_atoms[i].orig_id, system->my_atoms[j].orig_id ),
// CEvd, CEclmb );
if( control->virial == 0 ) {
rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
}
else { /* NPT, iNPT or sNPT */
/* for pressure coupling, terms not related to bond order
derivatives are added directly into pressure vector/tensor */
rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f[i], -1., temp );
rvec_Add( workspace->f[j], temp );
rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
rvec_Add( data->my_ext_press, ext_press );
// fprintf( stderr, "nonbonded(%d,%d): rel_box (%f %f %f)
// force(%f %f %f) ext_press (%12.6f %12.6f %12.6f)\n",
// i, j, nbr_pj->rel_box[0], nbr_pj->rel_box[1], nbr_pj->rel_box[2],
// temp[0], temp[1], temp[2],
// data->ext_press[0], data->ext_press[1], data->ext_press[2] );
}
#ifdef TEST_ENERGY
// fprintf( out_control->evdw,
// "%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f%12.9f\n",
// workspace->Tap[7],workspace->Tap[6],workspace->Tap[5],
// workspace->Tap[4],workspace->Tap[3],workspace->Tap[2],
// workspace->Tap[1], Tap );
//fprintf( out_control->evdw, "%6d%6d%24.15e%24.15e%24.15e\n",
fprintf( out_control->evdw, "%6d%6d%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
r_ij, e_vdW, data->my_en.e_vdW );
//fprintf(out_control->ecou,"%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
fprintf( out_control->ecou, "%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
r_ij, system->my_atoms[i].q, system->my_atoms[j].q,
e_ele, data->my_en.e_ele );
#endif
#ifdef TEST_FORCES
rvec_ScaledAdd( workspace->f_vdw[i], -CEvd, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_vdw[j], +CEvd, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_ele[i], -CEclmb, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_ele[j], +CEclmb, nbr_pj->dvec );
#endif
}
}
}
#if defined(DEBUG)
fprintf( stderr, "nonbonded: ext_press (%12.6f %12.6f %12.6f)\n",
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
MPI_Barrier( MPI_COMM_WORLD );
#endif
Compute_Polarization_Energy( system, data );
}
void Tabulated_vdW_Coulomb_Energy( reax_system *system,control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists,
output_controls *out_control )
{
int i, j, pj, r, natoms, steps, update_freq, update_energies;
int type_i, type_j, tmin, tmax;
int start_i, end_i, orig_i, orig_j;
real r_ij, base, dif;
real e_vdW, e_ele;
real CEvd, CEclmb;
rvec temp, ext_press;
far_neighbor_data *nbr_pj;
reax_list *far_nbrs;
LR_lookup_table *t;
natoms = system->n;
far_nbrs = (*lists) + FAR_NBRS;
steps = data->step - data->prev_steps;
update_freq = out_control->energy_update_freq;
update_energies = update_freq > 0 && steps % update_freq == 0;
e_ele = e_vdW = 0;
for( i = 0; i < natoms; ++i ) {
type_i = system->my_atoms[i].type;
start_i = Start_Index(i,far_nbrs);
end_i = End_Index(i,far_nbrs);
orig_i = system->my_atoms[i].orig_id;
for( pj = start_i; pj < end_i; ++pj ) {
nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
j = nbr_pj->nbr;
orig_j = system->my_atoms[j].orig_id;
if( nbr_pj->d <= control->nonb_cut && (j < natoms || orig_i < orig_j) ) {
j = nbr_pj->nbr;
type_j = system->my_atoms[j].type;
r_ij = nbr_pj->d;
tmin = MIN( type_i, type_j );
tmax = MAX( type_i, type_j );
t = &( LR[tmin][tmax] );
//t = &( LR[type_i][type_j] );
/* Cubic Spline Interpolation */
r = (int)(r_ij * t->inv_dx);
if( r == 0 ) ++r;
base = (real)(r+1) * t->dx;
dif = r_ij - base;
//fprintf(stderr, "r: %f, i: %d, base: %f, dif: %f\n", r, i, base, dif);
if( update_energies ) {
e_vdW = ((t->vdW[r].d*dif + t->vdW[r].c)*dif + t->vdW[r].b)*dif +
t->vdW[r].a;
e_ele = ((t->ele[r].d*dif + t->ele[r].c)*dif + t->ele[r].b)*dif +
t->ele[r].a;
e_ele *= system->my_atoms[i].q * system->my_atoms[j].q;
data->my_en.e_vdW += e_vdW;
data->my_en.e_ele += e_ele;
}
CEvd = ((t->CEvd[r].d*dif + t->CEvd[r].c)*dif + t->CEvd[r].b)*dif +
t->CEvd[r].a;
CEclmb = ((t->CEclmb[r].d*dif+t->CEclmb[r].c)*dif+t->CEclmb[r].b)*dif +
t->CEclmb[r].a;
CEclmb *= system->my_atoms[i].q * system->my_atoms[j].q;
if( control->virial == 0 ) {
rvec_ScaledAdd( workspace->f[i], -(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( workspace->f[j], +(CEvd + CEclmb), nbr_pj->dvec );
}
else { // NPT, iNPT or sNPT
/* for pressure coupling, terms not related to bond order derivatives
are added directly into pressure vector/tensor */
rvec_Scale( temp, CEvd + CEclmb, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f[i], -1., temp );
rvec_Add( workspace->f[j], temp );
rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
rvec_Add( data->my_ext_press, ext_press );
}
#ifdef TEST_ENERGY
//fprintf( out_control->evdw, "%6d%6d%24.15e%24.15e%24.15e\n",
fprintf( out_control->evdw, "%6d%6d%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
r_ij, e_vdW, data->my_en.e_vdW );
//fprintf(out_control->ecou,"%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
fprintf( out_control->ecou, "%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id, system->my_atoms[j].orig_id,
r_ij, system->my_atoms[i].q, system->my_atoms[j].q,
e_ele, data->my_en.e_ele );
#endif
#ifdef TEST_FORCES
rvec_ScaledAdd( workspace->f_vdw[i], -CEvd, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_vdw[j], +CEvd, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_ele[i], -CEclmb, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_ele[j], +CEclmb, nbr_pj->dvec );
#endif
}
}
}
Compute_Polarization_Energy( system, data );
}
void Compute_Polarization_Energy( reax_system *system, simulation_data *data )
{
int i, type_i;
real q;
data->my_en.e_pol = 0.0;
for( i = 0; i < system->n; i++ ) {
q = system->my_atoms[i].q;
type_i = system->my_atoms[i].type;
data->my_en.e_pol +=
KCALpMOL_to_EV * (system->reax_param.sbp[type_i].chi * q +
(system->reax_param.sbp[type_i].eta / 2.) * SQR(q));
}
}
void LR_vdW_Coulomb( reax_system *system, storage *workspace,
int i, int j, real r_ij, LR_data *lr )
{
real p_vdW1 = system->reax_param.gp.l[28];
real p_vdW1i = 1.0 / p_vdW1;
real powr_vdW1, powgi_vdW1;
real tmp, fn13, exp1, exp2;
real Tap, dTap, dfn13;
real dr3gamij_1, dr3gamij_3;
real e_core, de_core;
two_body_parameters *twbp;
twbp = &(system->reax_param.tbp[i][j]);
e_core = 0;
de_core = 0;
/* calculate taper and its derivative */
Tap = workspace->Tap[7] * r_ij + workspace->Tap[6];
Tap = Tap * r_ij + workspace->Tap[5];
Tap = Tap * r_ij + workspace->Tap[4];
Tap = Tap * r_ij + workspace->Tap[3];
Tap = Tap * r_ij + workspace->Tap[2];
Tap = Tap * r_ij + workspace->Tap[1];
Tap = Tap * r_ij + workspace->Tap[0];
dTap = 7*workspace->Tap[7] * r_ij + 6*workspace->Tap[6];
dTap = dTap * r_ij + 5*workspace->Tap[5];
dTap = dTap * r_ij + 4*workspace->Tap[4];
dTap = dTap * r_ij + 3*workspace->Tap[3];
dTap = dTap * r_ij + 2*workspace->Tap[2];
dTap += workspace->Tap[1]/r_ij;
/*vdWaals Calculations*/
if(system->reax_param.gp.vdw_type==1 || system->reax_param.gp.vdw_type==3)
{ // shielding
powr_vdW1 = pow(r_ij, p_vdW1);
powgi_vdW1 = pow( 1.0 / twbp->gamma_w, p_vdW1);
fn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i );
exp1 = exp( twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
exp2 = exp( 0.5 * twbp->alpha * (1.0 - fn13 / twbp->r_vdW) );
lr->e_vdW = Tap * twbp->D * (exp1 - 2.0 * exp2);
dfn13 = pow( powr_vdW1 + powgi_vdW1, p_vdW1i-1.0) * pow(r_ij, p_vdW1-2.0);
lr->CEvd = dTap * twbp->D * (exp1 - 2.0 * exp2) -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
}
else{ // no shielding
exp1 = exp( twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
exp2 = exp( 0.5 * twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
lr->e_vdW = Tap * twbp->D * (exp1 - 2.0 * exp2);
lr->CEvd = dTap * twbp->D * (exp1 - 2.0 * exp2) -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2);
}
if(system->reax_param.gp.vdw_type==2 || system->reax_param.gp.vdw_type==3)
{ // innner wall
e_core = twbp->ecore * exp(twbp->acore * (1.0-(r_ij/twbp->rcore)));
lr->e_vdW += Tap * e_core;
de_core = -(twbp->acore/twbp->rcore) * e_core;
lr->CEvd += dTap * e_core + Tap * de_core;
}
/* Coulomb calculations */
dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 );
tmp = Tap / dr3gamij_3;
lr->H = EV_to_KCALpMOL * tmp;
lr->e_ele = C_ele * tmp;
// fprintf( stderr,
// "i:%d(%d), j:%d(%d), gamma:%f, Tap:%f, dr3gamij_3:%f, qi: %f, qj: %f\n",
// i, system->my_atoms[i].type, j, system->my_atoms[j].type,
// twbp->gamma, Tap, dr3gamij_3,
// system->my_atoms[i].q, system->my_atoms[j].q );
lr->CEclmb = C_ele * ( dTap - Tap * r_ij / dr3gamij_1 ) / dr3gamij_3;
// fprintf( stdout, "%d %d\t%g\t%g %g\t%g %g\t%g %g\n",
// i+1, j+1, r_ij, e_vdW, CEvd * r_ij,
// system->my_atoms[i].q, system->my_atoms[j].q, e_ele, CEclmb * r_ij );
// fprintf(stderr,"LR_Lookup: %3d %3d %5.3f-%8.5f %8.5f %8.5f %8.5f %8.5f\n",
// i, j, r_ij, lr->H, lr->e_vdW, lr->CEvd, lr->e_ele, lr->CEclmb ); */
}

View File

@ -0,0 +1,37 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __NONBONDED_H_
#define __NONBONDED_H_
#include "reaxc_types.h"
void vdW_Coulomb_Energy( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Tabulated_vdW_Coulomb_Energy( reax_system*, control_params*,
simulation_data*, storage*,
reax_list**, output_controls* );
void Compute_Polarization_Energy( reax_system*, simulation_data* );
void LR_vdW_Coulomb( reax_system*, storage*, int, int, real, LR_data* );
#endif

View File

@ -0,0 +1,254 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "reset_tools.h"
#include "list.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_reset_tools.h"
#include "reaxc_list.h"
#include "reaxc_tool_box.h"
#include "reaxc_vector.h"
#endif
void Reset_Atoms( reax_system* system, control_params *control )
{
int i;
reax_atom *atom;
system->numH = 0;
if( control->hbond_cut > 0 )
for( i = 0; i < system->n; ++i ) {
atom = &(system->my_atoms[i]);
if( system->reax_param.sbp[ atom->type ].p_hbond == 1 )
atom->Hindex = system->numH++;
else atom->Hindex = -1;
}
}
void Reset_Energies( energy_data *en )
{
en->e_bond = 0;
en->e_ov = 0;
en->e_un = 0;
en->e_lp = 0;
en->e_ang = 0;
en->e_pen = 0;
en->e_coa = 0;
en->e_hb = 0;
en->e_tor = 0;
en->e_con = 0;
en->e_vdW = 0;
en->e_ele = 0;
en->e_pol = 0;
en->e_pot = 0;
en->e_kin = 0;
en->e_tot = 0;
}
void Reset_Temperatures( simulation_data *data )
{
data->therm.T = 0;
}
void Reset_Pressures( simulation_data *data )
{
data->flex_bar.P_scalar = 0;
rtensor_MakeZero( data->flex_bar.P );
data->iso_bar.P = 0;
rvec_MakeZero( data->int_press );
rvec_MakeZero( data->my_ext_press );
rvec_MakeZero( data->ext_press );
}
void Reset_Simulation_Data( simulation_data* data, int virial )
{
Reset_Energies( &data->my_en );
Reset_Energies( &data->sys_en );
Reset_Temperatures( data );
//if( virial )
Reset_Pressures( data );
}
void Reset_Timing( reax_timing *rt )
{
rt->total = Get_Time();
rt->comm = 0;
rt->nbrs = 0;
rt->init_forces = 0;
rt->bonded = 0;
rt->nonb = 0;
rt->qEq = 0;
rt->s_matvecs = 0;
rt->t_matvecs = 0;
}
#ifdef TEST_FORCES
void Reset_Test_Forces( reax_system *system, storage *workspace )
{
memset( workspace->f_ele, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_vdw, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_bo, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_be, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_lp, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_ov, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_un, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_ang, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_coa, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_pen, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_hb, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_tor, 0, system->total_cap * sizeof(rvec) );
memset( workspace->f_con, 0, system->total_cap * sizeof(rvec) );
}
#endif
void Reset_Workspace( reax_system *system, storage *workspace )
{
memset( workspace->total_bond_order, 0, system->total_cap * sizeof( real ) );
memset( workspace->dDeltap_self, 0, system->total_cap * sizeof( rvec ) );
memset( workspace->CdDelta, 0, system->total_cap * sizeof( real ) );
memset( workspace->f, 0, system->total_cap * sizeof( rvec ) );
#ifdef TEST_FORCES
memset( workspace->dDelta, 0, sizeof(rvec) * system->total_cap );
Reset_Test_Forces( system, workspace );
#endif
}
void Reset_Grid( grid *g )
{
int i, j, k;
for( i = 0; i < g->ncells[0]; i++ )
for( j = 0; j < g->ncells[1]; j++ )
for( k = 0; k < g->ncells[2]; k++ ) {
g->cells[i][j][k].top = 0;
g->cells[i][j][k].str = 0;
g->cells[i][j][k].end = 0;
}
}
void Reset_Out_Buffers( mpi_out_data *out_buf, int n )
{
int i;
for( i = 0; i < n; ++i )
out_buf[i].cnt = 0;
}
void Reset_Neighbor_Lists( reax_system *system, control_params *control,
storage *workspace, reax_list **lists,
MPI_Comm comm )
{
int i, total_bonds, Hindex, total_hbonds;
reax_list *bonds, *hbonds;
/* bonds list */
if( system->N > 0 ){
bonds = (*lists) + BONDS;
total_bonds = 0;
/* reset start-end indexes */
for( i = 0; i < system->N; ++i ) {
Set_Start_Index( i, total_bonds, bonds );
Set_End_Index( i, total_bonds, bonds );
total_bonds += system->my_atoms[i].num_bonds;
}
/* is reallocation needed? */
if( total_bonds >= bonds->num_intrs * DANGER_ZONE ) {
workspace->realloc.bonds = 1;
if( total_bonds >= bonds->num_intrs ) {
fprintf(stderr,
"p%d: not enough space for bonds! total=%d allocated=%d\n",
system->my_rank, total_bonds, bonds->num_intrs );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
}
}
// fprintf( stderr, "p%d: n:%d num_intrs:%d num_H:%d\n",
// system->my_rank, hbonds->n, hbonds->num_intrs, workspace->num_H );
// MPI_Barrier( comm );
/* hbonds list */
if( control->hbond_cut > 0 && system->numH > 0 ) {
hbonds = (*lists) + HBONDS;
total_hbonds = 0;
/* reset start-end indexes */
for( i = 0; i < system->n; ++i ) {
Hindex = system->my_atoms[i].Hindex;
if( Hindex > -1 ) {
Set_Start_Index( Hindex, total_hbonds, hbonds );
Set_End_Index( Hindex, total_hbonds, hbonds );
total_hbonds += system->my_atoms[i].num_hbonds;
}
}
/* is reallocation needed? */
if( total_hbonds >= hbonds->num_intrs * 0.90/*DANGER_ZONE*/ ) {
workspace->realloc.hbonds = 1;
if( total_hbonds >= hbonds->num_intrs ) {
fprintf(stderr,
"p%d: not enough space for hbonds! total=%d allocated=%d\n",
system->my_rank, total_hbonds, hbonds->num_intrs );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
}
}
// fprintf( stderr, "p%d: cleared hbonds\n", system->my_rank );
// MPI_Barrier( comm );
}
void Reset( reax_system *system, control_params *control, simulation_data *data,
storage *workspace, reax_list **lists, MPI_Comm comm )
{
Reset_Atoms( system, control );
Reset_Simulation_Data( data, control->virial );
Reset_Workspace( system, workspace );
Reset_Neighbor_Lists( system, control, workspace, lists, comm );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: reset done\n", system->my_rank, data->step );
MPI_Barrier( comm );
#endif
}

View File

@ -0,0 +1,40 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __RESET_TOOLS_H_
#define __RESET_TOOLS_H_
#include "reaxc_types.h"
void Reset_Pressures( simulation_data* );
void Reset_Simulation_Data( simulation_data*, int );
void Reset_Timing( reax_timing* );
void Reset_Workspace( reax_system*, storage* );
void Reset_Grid( grid* );
void Reset_Out_Buffers( mpi_out_data*, int );
void Reset_Neighbor_Lists( reax_system*, control_params*, storage*,
reax_list**, MPI_Comm );
void Reset( reax_system*, control_params*, simulation_data*, storage*,
reax_list**, MPI_Comm );
#ifdef TEST_FORCES
void Reset_Test_Forces( reax_system*, storage* );
#endif
#endif

View File

@ -0,0 +1,411 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "system_props.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_system_props.h"
#include "reaxc_tool_box.h"
#include "reaxc_vector.h"
#endif
void Temperature_Control( control_params *control, simulation_data *data )
{
real tmp;
if( control->T_mode == 1 ) {// step-wise temperature control
if((data->step-data->prev_steps) % ((int)(control->T_freq/control->dt))==0){
if( fabs( control->T - control->T_final ) >= fabs( control->T_rate ) )
control->T += control->T_rate;
else control->T = control->T_final;
}
}
else if( control->T_mode == 2 ) { // constant slope control
tmp = control->T_rate * control->dt / control->T_freq;
if( fabs( control->T - control->T_final ) >= fabs( tmp ) )
control->T += tmp;
}
}
void Compute_Kinetic_Energy( reax_system* system, simulation_data* data,
MPI_Comm comm )
{
int i;
rvec p;
real m;
data->my_en.e_kin = 0.0;
data->sys_en.e_kin = 0.0;
data->therm.T = 0;
for( i = 0; i < system->n; i++ ) {
m = system->reax_param.sbp[system->my_atoms[i].type].mass;
rvec_Scale( p, m, system->my_atoms[i].v );
data->my_en.e_kin += 0.5 * rvec_Dot( p, system->my_atoms[i].v );
}
MPI_Allreduce( &data->my_en.e_kin, &data->sys_en.e_kin,
1, MPI_DOUBLE, MPI_SUM, comm );
data->therm.T = (2. * data->sys_en.e_kin) / (data->N_f * K_B);
// avoid T being an absolute zero, might cause F.P.E!
if( fabs(data->therm.T) < ALMOST_ZERO )
data->therm.T = ALMOST_ZERO;
}
void Compute_System_Energy( reax_system *system, simulation_data *data,
MPI_Comm comm )
{
real my_en[15], sys_en[15];
my_en[0] = data->my_en.e_bond;
my_en[1] = data->my_en.e_ov;
my_en[2] = data->my_en.e_un;
my_en[3] = data->my_en.e_lp;
my_en[4] = data->my_en.e_ang;
my_en[5] = data->my_en.e_pen;
my_en[6] = data->my_en.e_coa;
my_en[7] = data->my_en.e_hb;
my_en[8] = data->my_en.e_tor;
my_en[9] = data->my_en.e_con;
my_en[10] = data->my_en.e_vdW;
my_en[11] = data->my_en.e_ele;
my_en[12] = data->my_en.e_pol;
my_en[13] = data->my_en.e_kin;
MPI_Reduce( my_en, sys_en, 14, MPI_DOUBLE, MPI_SUM, MASTER_NODE, comm );
data->my_en.e_pot = data->my_en.e_bond +
data->my_en.e_ov + data->my_en.e_un + data->my_en.e_lp +
data->my_en.e_ang + data->my_en.e_pen + data->my_en.e_coa +
data->my_en.e_hb +
data->my_en.e_tor + data->my_en.e_con +
data->my_en.e_vdW + data->my_en.e_ele + data->my_en.e_pol;
data->my_en.e_tot = data->my_en.e_pot + E_CONV * data->my_en.e_kin;
if( system->my_rank == MASTER_NODE ) {
data->sys_en.e_bond = sys_en[0];
data->sys_en.e_ov = sys_en[1];
data->sys_en.e_un = sys_en[2];
data->sys_en.e_lp = sys_en[3];
data->sys_en.e_ang = sys_en[4];
data->sys_en.e_pen = sys_en[5];
data->sys_en.e_coa = sys_en[6];
data->sys_en.e_hb = sys_en[7];
data->sys_en.e_tor = sys_en[8];
data->sys_en.e_con = sys_en[9];
data->sys_en.e_vdW = sys_en[10];
data->sys_en.e_ele = sys_en[11];
data->sys_en.e_pol = sys_en[12];
data->sys_en.e_kin = sys_en[13];
data->sys_en.e_pot = data->sys_en.e_bond +
data->sys_en.e_ov + data->sys_en.e_un + data->sys_en.e_lp +
data->sys_en.e_ang + data->sys_en.e_pen + data->sys_en.e_coa +
data->sys_en.e_hb +
data->sys_en.e_tor + data->sys_en.e_con +
data->sys_en.e_vdW + data->sys_en.e_ele + data->sys_en.e_pol;
data->sys_en.e_tot = data->sys_en.e_pot + E_CONV * data->sys_en.e_kin;
}
}
void Compute_Total_Mass( reax_system *system, simulation_data *data,
MPI_Comm comm )
{
int i;
real tmp;
tmp = 0;
for( i = 0; i < system->n; i++ )
tmp += system->reax_param.sbp[ system->my_atoms[i].type ].mass;
MPI_Allreduce( &tmp, &data->M, 1, MPI_DOUBLE, MPI_SUM, comm );
data->inv_M = 1. / data->M;
}
void Compute_Center_of_Mass( reax_system *system, simulation_data *data,
mpi_datatypes *mpi_data, MPI_Comm comm )
{
int i;
real m, det; //xx, xy, xz, yy, yz, zz;
real tmp_mat[6], tot_mat[6];
rvec my_xcm, my_vcm, my_amcm, my_avcm;
rvec tvec, diff;
rtensor mat, inv;
rvec_MakeZero( my_xcm ); // position of CoM
rvec_MakeZero( my_vcm ); // velocity of CoM
rvec_MakeZero( my_amcm ); // angular momentum of CoM
rvec_MakeZero( my_avcm ); // angular velocity of CoM
/* Compute the position, vel. and ang. momentum about the centre of mass */
for( i = 0; i < system->n; ++i ) {
m = system->reax_param.sbp[ system->my_atoms[i].type ].mass;
rvec_ScaledAdd( my_xcm, m, system->my_atoms[i].x );
rvec_ScaledAdd( my_vcm, m, system->my_atoms[i].v );
rvec_Cross( tvec, system->my_atoms[i].x, system->my_atoms[i].v );
rvec_ScaledAdd( my_amcm, m, tvec );
}
MPI_Allreduce( my_xcm, data->xcm, 3, MPI_DOUBLE, MPI_SUM, comm );
MPI_Allreduce( my_vcm, data->vcm, 3, MPI_DOUBLE, MPI_SUM, comm );
MPI_Allreduce( my_amcm, data->amcm, 3, MPI_DOUBLE, MPI_SUM, comm );
rvec_Scale( data->xcm, data->inv_M, data->xcm );
rvec_Scale( data->vcm, data->inv_M, data->vcm );
rvec_Cross( tvec, data->xcm, data->vcm );
rvec_ScaledAdd( data->amcm, -data->M, tvec );
data->etran_cm = 0.5 * data->M * rvec_Norm_Sqr( data->vcm );
/* Calculate and then invert the inertial tensor */
for( i = 0; i < 6; ++i )
tmp_mat[i] = 0;
//my_xx = my_xy = my_xz = my_yy = my_yz = my_zz = 0;
for( i = 0; i < system->n; ++i ){
m = system->reax_param.sbp[ system->my_atoms[i].type ].mass;
rvec_ScaledSum( diff, 1., system->my_atoms[i].x, -1., data->xcm );
tmp_mat[0]/*my_xx*/ += diff[0] * diff[0] * m;
tmp_mat[1]/*my_xy*/ += diff[0] * diff[1] * m;
tmp_mat[2]/*my_xz*/ += diff[0] * diff[2] * m;
tmp_mat[3]/*my_yy*/ += diff[1] * diff[1] * m;
tmp_mat[4]/*my_yz*/ += diff[1] * diff[2] * m;
tmp_mat[5]/*my_zz*/ += diff[2] * diff[2] * m;
}
MPI_Reduce( tmp_mat, tot_mat, 6, MPI_DOUBLE, MPI_SUM, MASTER_NODE, comm );
if( system->my_rank == MASTER_NODE ) {
mat[0][0] = tot_mat[3] + tot_mat[5]; // yy + zz;
mat[0][1] = mat[1][0] = -tot_mat[1]; // -xy;
mat[0][2] = mat[2][0] = -tot_mat[2]; // -xz;
mat[1][1] = tot_mat[0] + tot_mat[5]; // xx + zz;
mat[2][1] = mat[1][2] = -tot_mat[4]; // -yz;
mat[2][2] = tot_mat[0] + tot_mat[3]; // xx + yy;
/* invert the inertial tensor */
det = ( mat[0][0] * mat[1][1] * mat[2][2] +
mat[0][1] * mat[1][2] * mat[2][0] +
mat[0][2] * mat[1][0] * mat[2][1] ) -
( mat[0][0] * mat[1][2] * mat[2][1] +
mat[0][1] * mat[1][0] * mat[2][2] +
mat[0][2] * mat[1][1] * mat[2][0] );
inv[0][0] = mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1];
inv[0][1] = mat[0][2] * mat[2][1] - mat[0][1] * mat[2][2];
inv[0][2] = mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1];
inv[1][0] = mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2];
inv[1][1] = mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0];
inv[1][2] = mat[0][2] * mat[1][0] - mat[0][0] * mat[1][2];
inv[2][0] = mat[1][0] * mat[2][1] - mat[2][0] * mat[1][1];
inv[2][1] = mat[2][0] * mat[0][1] - mat[0][0] * mat[2][1];
inv[2][2] = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
if( det > ALMOST_ZERO )
rtensor_Scale( inv, 1./det, inv );
else rtensor_MakeZero( inv );
/* Compute the angular velocity about the centre of mass */
rtensor_MatVec( data->avcm, inv, data->amcm );
}
MPI_Bcast( data->avcm, 3, MPI_DOUBLE, MASTER_NODE, comm );
/* Compute the rotational energy */
data->erot_cm = 0.5 * E_CONV * rvec_Dot( data->avcm, data->amcm );
#if defined(DEBUG)
fprintf( stderr, "xcm: %24.15e %24.15e %24.15e\n",
data->xcm[0], data->xcm[1], data->xcm[2] );
fprintf( stderr, "vcm: %24.15e %24.15e %24.15e\n",
data->vcm[0], data->vcm[1], data->vcm[2] );
fprintf( stderr, "amcm: %24.15e %24.15e %24.15e\n",
data->amcm[0], data->amcm[1], data->amcm[2] );
/* fprintf( stderr, "mat: %f %f %f\n %f %f %f\n %f %f %f\n",
mat[0][0], mat[0][1], mat[0][2],
mat[1][0], mat[1][1], mat[1][2],
mat[2][0], mat[2][1], mat[2][2] );
fprintf( stderr, "inv: %g %g %g\n %g %g %g\n %g %g %g\n",
inv[0][0], inv[0][1], inv[0][2],
inv[1][0], inv[1][1], inv[1][2],
inv[2][0], inv[2][1], inv[2][2] ); */
fprintf( stderr, "avcm: %24.15e %24.15e %24.15e\n",
data->avcm[0], data->avcm[1], data->avcm[2] );
#endif
}
/* IMPORTANT: This function assumes that current kinetic energy
* the system is already computed
*
* IMPORTANT: In Klein's paper, it is stated that a dU/dV term needs
* to be added when there are long-range interactions or long-range
* corrections to short-range interactions present.
* We may want to add that for more accuracy.
*/
void Compute_Pressure(reax_system* system, control_params *control,
simulation_data* data, mpi_datatypes *mpi_data)
{
int i;
reax_atom *p_atom;
rvec tmp, tx, int_press;
simulation_box *big_box = &(system->big_box);
/* Calculate internal pressure */
rvec_MakeZero( int_press );
// 0: both int and ext, 1: ext only, 2: int only
if( control->press_mode == 0 || control->press_mode == 2 ) {
for( i = 0; i < system->n; ++i ) {
p_atom = &( system->my_atoms[i] );
/* transform x into unitbox coordinates */
Transform_to_UnitBox( p_atom->x, big_box, 1, tx );
/* this atom's contribution to internal pressure */
rvec_Multiply( tmp, p_atom->f, tx );
rvec_Add( int_press, tmp );
#if defined(DEBUG)
fprintf( stderr, "%8d%8.2f%8.2f%8.2f",
i+1, p_atom->x[0], p_atom->x[1], p_atom->x[2] );
fprintf( stderr, "%8.2f%8.2f%8.2f",
p_atom->f[0], p_atom->f[1], p_atom->f[2] );
fprintf( stderr, "%8.2f%8.2f%8.2f\n",
int_press[0], int_press[1], int_press[2] );
#endif
}
}
/* sum up internal and external pressure */
#if defined(DEBUG)
fprintf(stderr,"p%d:p_int(%10.5f %10.5f %10.5f)p_ext(%10.5f %10.5f %10.5f)\n",
system->my_rank, int_press[0], int_press[1], int_press[2],
data->my_ext_press[0], data->my_ext_press[1], data->my_ext_press[2] );
#endif
MPI_Allreduce( int_press, data->int_press,
3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D );
MPI_Allreduce( data->my_ext_press, data->ext_press,
3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D );
#if defined(DEBUG)
fprintf( stderr, "p%d: %10.5f %10.5f %10.5f\n",
system->my_rank,
data->int_press[0], data->int_press[1], data->int_press[2] );
fprintf( stderr, "p%d: %10.5f %10.5f %10.5f\n",
system->my_rank,
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
/* kinetic contribution */
data->kin_press = 2.*(E_CONV*data->sys_en.e_kin) / (3.*big_box->V*P_CONV);
/* Calculate total pressure in each direction */
data->tot_press[0] = data->kin_press -
(( data->int_press[0] + data->ext_press[0] ) /
( big_box->box_norms[1] * big_box->box_norms[2] * P_CONV ));
data->tot_press[1] = data->kin_press -
(( data->int_press[1] + data->ext_press[1] ) /
( big_box->box_norms[0] * big_box->box_norms[2] * P_CONV ));
data->tot_press[2] = data->kin_press -
(( data->int_press[2] + data->ext_press[2] ) /
( big_box->box_norms[0] * big_box->box_norms[1] * P_CONV ));
/* Average pressure for the whole box */
data->iso_bar.P =
( data->tot_press[0] + data->tot_press[1] + data->tot_press[2] ) / 3.;
}
/*
void Compute_Pressure_Isotropic_Klein( reax_system* system,
simulation_data* data )
{
int i;
reax_atom *p_atom;
rvec dx;
// IMPORTANT: This function assumes that current kinetic energy and
// the center of mass of the system is already computed before.
data->iso_bar.P = 2.0 * data->my_en.e_kin;
for( i = 0; i < system->N; ++i ) {
p_atom = &( system->my_atoms[i] );
rvec_ScaledSum(dx,1.0,p_atom->x,-1.0,data->xcm);
data->iso_bar.P += ( -F_CONV * rvec_Dot(p_atom->f, dx) );
}
data->iso_bar.P /= (3.0 * system->my_box.V);
// IMPORTANT: In Klein's paper, it is stated that a dU/dV term needs
// to be added when there are long-range interactions or long-range
// corrections to short-range interactions present.
// We may want to add that for more accuracy.
}
void Compute_Pressure( reax_system* system, simulation_data* data )
{
int i;
reax_atom *p_atom;
rtensor temp;
rtensor_MakeZero( data->flex_bar.P );
for( i = 0; i < system->N; ++i ) {
p_atom = &( system->my_atoms[i] );
// Distance_on_T3_Gen( data->rcm, p_atom->x, &(system->my_box), &dx );
rvec_OuterProduct( temp, p_atom->v, p_atom->v );
rtensor_ScaledAdd( data->flex_bar.P,
system->reax_param.sbp[ p_atom->type ].mass, temp );
// rvec_OuterProduct(temp,workspace->virial_forces[i],p_atom->x); //dx);
rtensor_ScaledAdd( data->flex_bar.P, -F_CONV, temp );
}
rtensor_Scale( data->flex_bar.P, 1.0 / system->my_box.V, data->flex_bar.P );
data->iso_bar.P = rtensor_Trace( data->flex_bar.P ) / 3.0;
}
*/

View File

@ -0,0 +1,41 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __SYSTEM_PROP_H_
#define __SYSTEM_PROP_H_
#include "reaxc_types.h"
void Temperature_Control( control_params*, simulation_data* );
void Compute_Kinetic_Energy( reax_system*, simulation_data*, MPI_Comm );
void Compute_System_Energy( reax_system*, simulation_data*, MPI_Comm );
void Compute_Total_Mass( reax_system*, simulation_data*, MPI_Comm );
void Compute_Center_of_Mass( reax_system*, simulation_data*,
mpi_datatypes*, MPI_Comm );
void Compute_Pressure( reax_system*, control_params*,
simulation_data*, mpi_datatypes* );
//void Compute_Pressure( reax_system*, simulation_data* );
#endif

View File

@ -0,0 +1,467 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_tool_box.h"
#endif
#if defined(PURE_REAX)
/************** taken from comm_tools.c **************/
int SumScan( int n, int me, int root, MPI_Comm comm )
{
int i, my_order, wsize;;
int *nbuf = NULL;
if( me == root ) {
MPI_Comm_size( comm, &wsize );
nbuf = (int *) calloc( wsize, sizeof(int) );
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
for( i = 0; i < wsize-1; ++i ) {
nbuf[i+1] += nbuf[i];
}
MPI_Scatter( nbuf, 1, MPI_INT, &my_order, 1, MPI_INT, root, comm );
free( nbuf );
}
else {
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
MPI_Scatter( nbuf, 1, MPI_INT, &my_order, 1, MPI_INT, root, comm );
}
return my_order;
}
void SumScanB( int n, int me, int wsize, int root, MPI_Comm comm, int *nbuf )
{
int i;
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
if( me == root ) {
for( i = 0; i < wsize-1; ++i )
nbuf[i+1] += nbuf[i];
}
MPI_Bcast( nbuf, wsize, MPI_INT, root, comm );
}
#endif
/************** taken from box.c **************/
void Transform( rvec x1, simulation_box *box, char flag, rvec x2 )
{
int i, j;
real tmp;
// printf(">x1: (%lf, %lf, %lf)\n",x1[0],x1[1],x1[2]);
if (flag > 0) {
for (i=0; i < 3; i++) {
tmp = 0.0;
for (j=0; j < 3; j++)
tmp += box->trans[i][j]*x1[j];
x2[i] = tmp;
}
}
else {
for (i=0; i < 3; i++) {
tmp = 0.0;
for (j=0; j < 3; j++)
tmp += box->trans_inv[i][j]*x1[j];
x2[i] = tmp;
}
}
// printf(">x2: (%lf, %lf, %lf)\n", x2[0], x2[1], x2[2]);
}
void Transform_to_UnitBox( rvec x1, simulation_box *box, char flag, rvec x2 )
{
Transform( x1, box, flag, x2 );
x2[0] /= box->box_norms[0];
x2[1] /= box->box_norms[1];
x2[2] /= box->box_norms[2];
}
/* determine whether point p is inside the box */
void Fit_to_Periodic_Box( simulation_box *box, rvec *p )
{
int i;
for( i = 0; i < 3; ++i ) {
if( (*p)[i] < box->min[i] ) {
/* handle lower coords */
while( (*p)[i] < box->min[i] )
(*p)[i] += box->box_norms[i];
}
else if( (*p)[i] >= box->max[i] ) {
/* handle higher coords */
while( (*p)[i] >= box->max[i] )
(*p)[i] -= box->box_norms[i];
}
}
}
#if defined(PURE_REAX)
/* determine the touch point, tp, of a box to
its neighbor denoted by the relative coordinate rl */
inline void Box_Touch_Point( simulation_box *box, ivec rl, rvec tp )
{
int d;
for( d = 0; d < 3; ++d )
if( rl[d] == -1 )
tp[d] = box->min[d];
else if( rl[d] == 0 )
tp[d] = NEG_INF - 1.;
else
tp[d] = box->max[d];
}
/* determine whether point p is inside the box */
/* assumes orthogonal box */
inline int is_Inside_Box( simulation_box *box, rvec p )
{
if( p[0] < box->min[0] || p[0] >= box->max[0] ||
p[1] < box->min[1] || p[1] >= box->max[1] ||
p[2] < box->min[2] || p[2] >= box->max[2] )
return 0;
return 1;
}
inline int iown_midpoint( simulation_box *box, rvec p1, rvec p2 )
{
rvec midp;
midp[0] = (p1[0] + p2[0]) / 2;
midp[1] = (p1[1] + p2[1]) / 2;
midp[2] = (p1[2] + p2[2]) / 2;
if( midp[0] < box->min[0] || midp[0] >= box->max[0] ||
midp[1] < box->min[1] || midp[1] >= box->max[1] ||
midp[2] < box->min[2] || midp[2] >= box->max[2] )
return 0;
return 1;
}
/**************** from grid.c ****************/
/* finds the closest point of grid cell cj to ci.
no need to consider periodic boundary conditions as in the serial case
because the box of a process is not periodic in itself */
inline void GridCell_Closest_Point( grid_cell *gci, grid_cell *gcj,
ivec ci, ivec cj, rvec cp )
{
int d;
for( d = 0; d < 3; d++ )
if( cj[d] > ci[d] )
cp[d] = gcj->min[d];
else if ( cj[d] == ci[d] )
cp[d] = NEG_INF - 1.;
else
cp[d] = gcj->max[d];
}
inline void GridCell_to_Box_Points( grid_cell *gc, ivec rl, rvec cp, rvec fp )
{
int d;
for( d = 0; d < 3; ++d )
if( rl[d] == -1 ) {
cp[d] = gc->min[d];
fp[d] = gc->max[d];
}
else if( rl[d] == 0 ) {
cp[d] = fp[d] = NEG_INF - 1.;
}
else{
cp[d] = gc->max[d];
fp[d] = gc->min[d];
}
}
inline real DistSqr_between_Special_Points( rvec sp1, rvec sp2 )
{
int i;
real d_sqr = 0;
for( i = 0; i < 3; ++i )
if( sp1[i] > NEG_INF && sp2[i] > NEG_INF )
d_sqr += SQR( sp1[i] - sp2[i] );
return d_sqr;
}
inline real DistSqr_to_Special_Point( rvec cp, rvec x )
{
int i;
real d_sqr = 0;
for( i = 0; i < 3; ++i )
if( cp[i] > NEG_INF )
d_sqr += SQR( cp[i] - x[i] );
return d_sqr;
}
inline int Relative_Coord_Encoding( ivec c )
{
return 9 * (c[0] + 1) + 3 * (c[1] + 1) + (c[2] + 1);
}
#endif
/************** from geo_tools.c *****************/
void Make_Point( real x, real y, real z, rvec* p )
{
(*p)[0] = x;
(*p)[1] = y;
(*p)[2] = z;
}
int is_Valid_Serial( storage *workspace, int serial )
{
// if( workspace->map_serials[ serial ] < 0 )
// {
// fprintf( stderr, "CONECT line includes invalid pdb serial number %d.\n",
// serial );
// fprintf( stderr, "Please correct the input file.Terminating...\n" );
// MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT );
// }
return SUCCESS;
}
int Check_Input_Range( int val, int lo, int hi, char *message, MPI_Comm comm )
{
if( val < lo || val > hi ) {
fprintf( stderr, "%s\nInput %d - Out of range %d-%d. Terminating...\n",
message, val, lo, hi );
MPI_Abort( comm, INVALID_INPUT );
}
return 1;
}
void Trim_Spaces( char *element )
{
int i, j;
for( i = 0; element[i] == ' '; ++i ); // skip initial space chars
for( j = i; j < (int)(strlen(element)) && element[j] != ' '; ++j )
element[j-i] = toupper( element[j] ); // make uppercase, offset to 0
element[j-i] = 0; // finalize the string
}
/************ from system_props.c *************/
struct timeval tim;
real t_end;
real Get_Time( )
{
gettimeofday(&tim, NULL );
return( tim.tv_sec + (tim.tv_usec / 1000000.0) );
}
real Get_Timing_Info( real t_start )
{
gettimeofday(&tim, NULL );
t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
return (t_end - t_start);
}
void Update_Timing_Info( real *t_start, real *timing )
{
gettimeofday(&tim, NULL );
t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
*timing += (t_end - *t_start);
*t_start = t_end;
}
/*********** from io_tools.c **************/
int Get_Atom_Type( reax_interaction *reax_param, char *s, MPI_Comm comm )
{
int i;
for( i = 0; i < reax_param->num_atom_types; ++i )
if( !strcmp( reax_param->sbp[i].name, s ) )
return i;
fprintf( stderr, "Unknown atom type %s. Terminating...\n", s );
MPI_Abort( comm, UNKNOWN_ATOM_TYPE );
return -1;
}
char *Get_Element( reax_system *system, int i )
{
return &( system->reax_param.sbp[system->my_atoms[i].type].name[0] );
}
char *Get_Atom_Name( reax_system *system, int i )
{
return &(system->my_atoms[i].name[0]);
}
int Allocate_Tokenizer_Space( char **line, char **backup, char ***tokens )
{
int i;
if( (*line = (char*) malloc( sizeof(char) * MAX_LINE )) == NULL )
return FAILURE;
if( (*backup = (char*) malloc( sizeof(char) * MAX_LINE )) == NULL )
return FAILURE;
if( (*tokens = (char**) malloc( sizeof(char*) * MAX_TOKENS )) == NULL )
return FAILURE;
for( i = 0; i < MAX_TOKENS; i++ )
if( ((*tokens)[i] = (char*) malloc(sizeof(char) * MAX_TOKEN_LEN)) == NULL )
return FAILURE;
return SUCCESS;
}
int Tokenize( char* s, char*** tok )
{
char test[MAX_LINE];
char *sep = "\t \n!=";
char *word;
int count=0;
strncpy( test, s, MAX_LINE );
for( word = strtok(test, sep); word; word = strtok(NULL, sep) ) {
strncpy( (*tok)[count], word, MAX_LINE );
count++;
}
return count;
}
/***************** taken from lammps ************************/
/* safe malloc */
void *smalloc( long n, char *name, MPI_Comm comm )
{
void *ptr;
if( n <= 0 ) {
fprintf( stderr, "WARNING: trying to allocate %ld bytes for array %s. ",
n, name );
fprintf( stderr, "returning NULL.\n" );
return NULL;
}
ptr = malloc( n );
if( ptr == NULL ) {
fprintf( stderr, "ERROR: failed to allocate %ld bytes for array %s",
n, name );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
return ptr;
}
/* safe calloc */
void *scalloc( int n, int size, char *name, MPI_Comm comm )
{
void *ptr;
if( n <= 0 ) {
fprintf( stderr, "WARNING: trying to allocate %d elements for array %s. ",
n, name );
fprintf( stderr, "returning NULL.\n" );
return NULL;
}
if( size <= 0 ) {
fprintf( stderr, "WARNING: elements size for array %s is %d. ",
name, size );
fprintf( stderr, "returning NULL.\n" );
return NULL;
}
ptr = calloc( n, size );
if( ptr == NULL ) {
fprintf( stderr, "ERROR: failed to allocate %d bytes for array %s",
n*size, name );
MPI_Abort( comm, INSUFFICIENT_MEMORY );
}
return ptr;
}
/* safe free */
void sfree( void *ptr, char *name )
{
if( ptr == NULL ) {
fprintf( stderr, "WARNING: trying to free the already NULL pointer %s!\n",
name );
return;
}
free( ptr );
ptr = NULL;
}

View File

@ -0,0 +1,69 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __TOOL_BOX_H_
#define __TOOL_BOX_H_
#include "reaxc_types.h"
#include "reaxc_defs.h"
/* from comm_tools.h */
int SumScan( int, int, int, MPI_Comm );
void SumScanB( int, int, int, int, MPI_Comm, int* );
/* from box.h */
void Transform_to_UnitBox( rvec, simulation_box*, char, rvec );
void Fit_to_Periodic_Box( simulation_box*, rvec* );
void Box_Touch_Point( simulation_box*, ivec, rvec );
int is_Inside_Box( simulation_box*, rvec );
int iown_midpoint( simulation_box*, rvec, rvec );
/* from grid.h */
void GridCell_Closest_Point( grid_cell*, grid_cell*, ivec, ivec, rvec );
void GridCell_to_Box_Points( grid_cell*, ivec, rvec, rvec );
real DistSqr_between_Special_Points( rvec, rvec );
real DistSqr_to_Special_Point( rvec, rvec );
int Relative_Coord_Encoding( ivec );
/* from geo_tools.h */
void Make_Point( real, real, real, rvec* );
int is_Valid_Serial( storage*, int );
int Check_Input_Range( int, int, int, char*, MPI_Comm );
void Trim_Spaces( char* );
/* from system_props.h */
real Get_Time( );
real Get_Timing_Info( real );
void Update_Timing_Info( real*, real* );
/* from io_tools.h */
int Get_Atom_Type( reax_interaction*, char*, MPI_Comm );
char *Get_Element( reax_system*, int );
char *Get_Atom_Name( reax_system*, int );
int Allocate_Tokenizer_Space( char**, char**, char*** );
int Tokenize( char*, char*** );
/* from lammps */
void *smalloc( long, char*, MPI_Comm );
void *scalloc( int, int, char*, MPI_Comm );
void sfree( void*, char* );
#endif

View File

@ -0,0 +1,590 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "torsion_angles.h"
#include "bond_orders.h"
#include "list.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_torsion_angles.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_tool_box.h"
#include "reaxc_vector.h"
#endif
#define MIN_SINE 1e-10
real Calculate_Omega( rvec dvec_ij, real r_ij,
rvec dvec_jk, real r_jk,
rvec dvec_kl, real r_kl,
rvec dvec_li, real r_li,
three_body_interaction_data *p_ijk,
three_body_interaction_data *p_jkl,
rvec dcos_omega_di, rvec dcos_omega_dj,
rvec dcos_omega_dk, rvec dcos_omega_dl,
output_controls *out_control )
{
real unnorm_cos_omega, unnorm_sin_omega, omega;
real sin_ijk, cos_ijk, sin_jkl, cos_jkl;
real htra, htrb, htrc, hthd, hthe, hnra, hnrc, hnhd, hnhe;
real arg, poem, tel;
rvec cross_jk_kl;
sin_ijk = sin( p_ijk->theta );
cos_ijk = cos( p_ijk->theta );
sin_jkl = sin( p_jkl->theta );
cos_jkl = cos( p_jkl->theta );
/* omega */
unnorm_cos_omega = -rvec_Dot(dvec_ij, dvec_jk) * rvec_Dot(dvec_jk, dvec_kl) +
SQR( r_jk ) * rvec_Dot( dvec_ij, dvec_kl );
rvec_Cross( cross_jk_kl, dvec_jk, dvec_kl );
unnorm_sin_omega = -r_jk * rvec_Dot( dvec_ij, cross_jk_kl );
omega = atan2( unnorm_sin_omega, unnorm_cos_omega );
/* derivatives */
/* coef for adjusments to cos_theta's */
/* rla = r_ij, rlb = r_jk, rlc = r_kl, r4 = r_li;
coshd = cos_ijk, coshe = cos_jkl;
sinhd = sin_ijk, sinhe = sin_jkl; */
htra = r_ij + cos_ijk * ( r_kl * cos_jkl - r_jk );
htrb = r_jk - r_ij * cos_ijk - r_kl * cos_jkl;
htrc = r_kl + cos_jkl * ( r_ij * cos_ijk - r_jk );
hthd = r_ij * sin_ijk * ( r_jk - r_kl * cos_jkl );
hthe = r_kl * sin_jkl * ( r_jk - r_ij * cos_ijk );
hnra = r_kl * sin_ijk * sin_jkl;
hnrc = r_ij * sin_ijk * sin_jkl;
hnhd = r_ij * r_kl * cos_ijk * sin_jkl;
hnhe = r_ij * r_kl * sin_ijk * cos_jkl;
poem = 2.0 * r_ij * r_kl * sin_ijk * sin_jkl;
if( poem < 1e-20 ) poem = 1e-20;
tel = SQR( r_ij ) + SQR( r_jk ) + SQR( r_kl ) - SQR( r_li ) -
2.0 * ( r_ij * r_jk * cos_ijk - r_ij * r_kl * cos_ijk * cos_jkl +
r_jk * r_kl * cos_jkl );
arg = tel / poem;
if( arg > 1.0 ) arg = 1.0;
if( arg < -1.0 ) arg = -1.0;
/* fprintf( out_control->etor,
"%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f%12.6f\n",
htra, htrb, htrc, hthd, hthe, hnra, hnrc, hnhd, hnhe );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
dvec_ij[0]/r_ij, dvec_ij[1]/r_ij, dvec_ij[2]/r_ij );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
-dvec_jk[0]/r_jk, -dvec_jk[1]/r_jk, -dvec_jk[2]/r_jk );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
-dvec_kl[0]/r_kl, -dvec_kl[1]/r_kl, -dvec_kl[2]/r_kl );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f%12.6f\n",
r_li, dvec_li[0], dvec_li[1], dvec_li[2] );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
poem, tel, arg ); */
/* fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
-p_ijk->dcos_dk[0]/sin_ijk, -p_ijk->dcos_dk[1]/sin_ijk,
-p_ijk->dcos_dk[2]/sin_ijk );
fprintf( out_control->etor, "%12.6f%12.6f%12.6f\n",
-p_jkl->dcos_dk[0]/sin_jkl, -p_jkl->dcos_dk[1]/sin_jkl,
-p_jkl->dcos_dk[2]/sin_jkl );*/
if( sin_ijk >= 0 && sin_ijk <= MIN_SINE ) sin_ijk = MIN_SINE;
else if( sin_ijk <= 0 && sin_ijk >= -MIN_SINE ) sin_ijk = -MIN_SINE;
if( sin_jkl >= 0 && sin_jkl <= MIN_SINE ) sin_jkl = MIN_SINE;
else if( sin_jkl <= 0 && sin_jkl >= -MIN_SINE ) sin_jkl = -MIN_SINE;
// dcos_omega_di
rvec_ScaledSum( dcos_omega_di, (htra-arg*hnra)/r_ij, dvec_ij, -1., dvec_li );
rvec_ScaledAdd( dcos_omega_di,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_dk );
rvec_Scale( dcos_omega_di, 2.0 / poem, dcos_omega_di );
// dcos_omega_dj
rvec_ScaledSum( dcos_omega_dj,-(htra-arg*hnra)/r_ij, dvec_ij,
-htrb / r_jk, dvec_jk );
rvec_ScaledAdd( dcos_omega_dj,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_dj );
rvec_ScaledAdd( dcos_omega_dj,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_di );
rvec_Scale( dcos_omega_dj, 2.0 / poem, dcos_omega_dj );
// dcos_omega_dk
rvec_ScaledSum( dcos_omega_dk,-(htrc-arg*hnrc)/r_kl, dvec_kl,
htrb / r_jk, dvec_jk );
rvec_ScaledAdd( dcos_omega_dk,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_di );
rvec_ScaledAdd( dcos_omega_dk,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_dj );
rvec_Scale( dcos_omega_dk, 2.0 / poem, dcos_omega_dk );
// dcos_omega_dl
rvec_ScaledSum( dcos_omega_dl, (htrc-arg*hnrc)/r_kl, dvec_kl, 1., dvec_li );
rvec_ScaledAdd( dcos_omega_dl,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_dk );
rvec_Scale( dcos_omega_dl, 2.0 / poem, dcos_omega_dl );
return omega;
}
void Torsion_Angles( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control )
{
int i, j, k, l, pi, pj, pk, pl, pij, plk, natoms;
int type_i, type_j, type_k, type_l;
int start_j, end_j, start_k, end_k;
int start_pj, end_pj, start_pk, end_pk;
int num_frb_intrs = 0;
real Delta_j, Delta_k;
real r_ij, r_jk, r_kl, r_li;
real BOA_ij, BOA_jk, BOA_kl;
real exp_tor2_ij, exp_tor2_jk, exp_tor2_kl;
real exp_tor1, exp_tor3_DjDk, exp_tor4_DjDk, exp_tor34_inv;
real exp_cot2_jk, exp_cot2_ij, exp_cot2_kl;
real fn10, f11_DjDk, dfn11, fn12;
real theta_ijk, theta_jkl;
real sin_ijk, sin_jkl;
real cos_ijk, cos_jkl;
real tan_ijk_i, tan_jkl_i;
real omega, cos_omega, cos2omega, cos3omega;
rvec dcos_omega_di, dcos_omega_dj, dcos_omega_dk, dcos_omega_dl;
real CV, cmn, CEtors1, CEtors2, CEtors3, CEtors4;
real CEtors5, CEtors6, CEtors7, CEtors8, CEtors9;
real Cconj, CEconj1, CEconj2, CEconj3;
real CEconj4, CEconj5, CEconj6;
real e_tor, e_con;
rvec dvec_li;
rvec force, ext_press;
ivec rel_box_jl;
// rtensor total_rtensor, temp_rtensor;
four_body_header *fbh;
four_body_parameters *fbp;
bond_data *pbond_ij, *pbond_jk, *pbond_kl;
bond_order_data *bo_ij, *bo_jk, *bo_kl;
three_body_interaction_data *p_ijk, *p_jkl;
real p_tor2 = system->reax_param.gp.l[23];
real p_tor3 = system->reax_param.gp.l[24];
real p_tor4 = system->reax_param.gp.l[25];
real p_cot2 = system->reax_param.gp.l[27];
reax_list *bonds = (*lists) + BONDS;
reax_list *thb_intrs = (*lists) + THREE_BODIES;
// char fname[100];
// FILE *ftor;
// sprintf( fname, "tor%d.out", system->my_rank );
// ftor = fopen( fname, "w" );
natoms = system->n;
for( j = 0; j < natoms; ++j ) {
type_j = system->my_atoms[j].type;
Delta_j = workspace->Delta_boc[j];
start_j = Start_Index(j, bonds);
end_j = End_Index(j, bonds);
for( pk = start_j; pk < end_j; ++pk ) {
pbond_jk = &( bonds->select.bond_list[pk] );
k = pbond_jk->nbr;
bo_jk = &( pbond_jk->bo_data );
BOA_jk = bo_jk->BO - control->thb_cut;
/* see if there are any 3-body interactions involving j&k
where j is the central atom. Otherwise there is no point in
trying to form a 4-body interaction out of this neighborhood */
if( system->my_atoms[j].orig_id < system->my_atoms[k].orig_id &&
bo_jk->BO > control->thb_cut/*0*/ && Num_Entries(pk, thb_intrs) ) {
start_k = Start_Index(k, bonds);
end_k = End_Index(k, bonds);
pj = pbond_jk->sym_index; // pj points to j on k's list
/* do the same check as above:
are there any 3-body interactions involving k&j
where k is the central atom */
if( Num_Entries(pj, thb_intrs) ) {
type_k = system->my_atoms[k].type;
Delta_k = workspace->Delta_boc[k];
r_jk = pbond_jk->d;
start_pk = Start_Index(pk, thb_intrs );
end_pk = End_Index(pk, thb_intrs );
start_pj = Start_Index(pj, thb_intrs );
end_pj = End_Index(pj, thb_intrs );
exp_tor2_jk = exp( -p_tor2 * BOA_jk );
exp_cot2_jk = exp( -p_cot2 * SQR(BOA_jk - 1.5) );
exp_tor3_DjDk = exp( -p_tor3 * (Delta_j + Delta_k) );
exp_tor4_DjDk = exp( p_tor4 * (Delta_j + Delta_k) );
exp_tor34_inv = 1.0 / (1.0 + exp_tor3_DjDk + exp_tor4_DjDk);
f11_DjDk = (2.0 + exp_tor3_DjDk) * exp_tor34_inv;
/* pick i up from j-k interaction where j is the central atom */
for( pi = start_pk; pi < end_pk; ++pi ) {
p_ijk = &( thb_intrs->select.three_body_list[pi] );
pij = p_ijk->pthb; // pij is pointer to i on j's bond_list
pbond_ij = &( bonds->select.bond_list[pij] );
bo_ij = &( pbond_ij->bo_data );
if( bo_ij->BO > control->thb_cut/*0*/ ) {
i = p_ijk->thb;
type_i = system->my_atoms[i].type;
r_ij = pbond_ij->d;
BOA_ij = bo_ij->BO - control->thb_cut;
theta_ijk = p_ijk->theta;
sin_ijk = sin( theta_ijk );
cos_ijk = cos( theta_ijk );
//tan_ijk_i = 1. / tan( theta_ijk );
if( sin_ijk >= 0 && sin_ijk <= MIN_SINE )
tan_ijk_i = cos_ijk / MIN_SINE;
else if( sin_ijk <= 0 && sin_ijk >= -MIN_SINE )
tan_ijk_i = cos_ijk / -MIN_SINE;
else tan_ijk_i = cos_ijk / sin_ijk;
exp_tor2_ij = exp( -p_tor2 * BOA_ij );
exp_cot2_ij = exp( -p_cot2 * SQR(BOA_ij -1.5) );
/* pick l up from j-k interaction where k is the central atom */
for( pl = start_pj; pl < end_pj; ++pl ) {
p_jkl = &( thb_intrs->select.three_body_list[pl] );
l = p_jkl->thb;
plk = p_jkl->pthb; //pointer to l on k's bond_list!
pbond_kl = &( bonds->select.bond_list[plk] );
bo_kl = &( pbond_kl->bo_data );
type_l = system->my_atoms[l].type;
fbh = &(system->reax_param.fbp[type_i][type_j]
[type_k][type_l]);
fbp = &(system->reax_param.fbp[type_i][type_j]
[type_k][type_l].prm[0]);
if( i != l && fbh->cnt &&
bo_kl->BO > control->thb_cut/*0*/ &&
bo_ij->BO * bo_jk->BO * bo_kl->BO > control->thb_cut/*0*/ ){
++num_frb_intrs;
r_kl = pbond_kl->d;
BOA_kl = bo_kl->BO - control->thb_cut;
theta_jkl = p_jkl->theta;
sin_jkl = sin( theta_jkl );
cos_jkl = cos( theta_jkl );
//tan_jkl_i = 1. / tan( theta_jkl );
if( sin_jkl >= 0 && sin_jkl <= MIN_SINE )
tan_jkl_i = cos_jkl / MIN_SINE;
else if( sin_jkl <= 0 && sin_jkl >= -MIN_SINE )
tan_jkl_i = cos_jkl / -MIN_SINE;
else tan_jkl_i = cos_jkl /sin_jkl;
rvec_ScaledSum( dvec_li, 1., system->my_atoms[i].x,
-1., system->my_atoms[l].x );
r_li = rvec_Norm( dvec_li );
/* omega and its derivative */
omega = Calculate_Omega( pbond_ij->dvec, r_ij,
pbond_jk->dvec, r_jk,
pbond_kl->dvec, r_kl,
dvec_li, r_li,
p_ijk, p_jkl,
dcos_omega_di, dcos_omega_dj,
dcos_omega_dk, dcos_omega_dl,
out_control );
cos_omega = cos( omega );
cos2omega = cos( 2. * omega );
cos3omega = cos( 3. * omega );
/* end omega calculations */
/* torsion energy */
exp_tor1 = exp( fbp->p_tor1 *
SQR(2.0 - bo_jk->BO_pi - f11_DjDk) );
exp_tor2_kl = exp( -p_tor2 * BOA_kl );
exp_cot2_kl = exp( -p_cot2 * SQR(BOA_kl - 1.5) );
fn10 = (1.0 - exp_tor2_ij) * (1.0 - exp_tor2_jk) *
(1.0 - exp_tor2_kl);
CV = 0.5 * ( fbp->V1 * (1.0 + cos_omega) +
fbp->V2 * exp_tor1 * (1.0 - cos2omega) +
fbp->V3 * (1.0 + cos3omega) );
data->my_en.e_tor += e_tor = fn10 * sin_ijk * sin_jkl * CV;
dfn11 = (-p_tor3 * exp_tor3_DjDk +
(p_tor3 * exp_tor3_DjDk - p_tor4 * exp_tor4_DjDk) *
(2.0 + exp_tor3_DjDk) * exp_tor34_inv) *
exp_tor34_inv;
CEtors1 = sin_ijk * sin_jkl * CV;
CEtors2 = -fn10 * 2.0 * fbp->p_tor1 * fbp->V2 * exp_tor1 *
(2.0 - bo_jk->BO_pi - f11_DjDk) * (1.0 - SQR(cos_omega)) *
sin_ijk * sin_jkl;
CEtors3 = CEtors2 * dfn11;
CEtors4 = CEtors1 * p_tor2 * exp_tor2_ij *
(1.0 - exp_tor2_jk) * (1.0 - exp_tor2_kl);
CEtors5 = CEtors1 * p_tor2 *
(1.0 - exp_tor2_ij) * exp_tor2_jk * (1.0 - exp_tor2_kl);
CEtors6 = CEtors1 * p_tor2 *
(1.0 - exp_tor2_ij) * (1.0 - exp_tor2_jk) * exp_tor2_kl;
cmn = -fn10 * CV;
CEtors7 = cmn * sin_jkl * tan_ijk_i;
CEtors8 = cmn * sin_ijk * tan_jkl_i;
CEtors9 = fn10 * sin_ijk * sin_jkl *
(0.5 * fbp->V1 - 2.0 * fbp->V2 * exp_tor1 * cos_omega +
1.5 * fbp->V3 * (cos2omega + 2.0 * SQR(cos_omega)));
/* end of torsion energy */
/* 4-body conjugation energy */
fn12 = exp_cot2_ij * exp_cot2_jk * exp_cot2_kl;
data->my_en.e_con += e_con =
fbp->p_cot1 * fn12 *
(1.0 + (SQR(cos_omega) - 1.0) * sin_ijk * sin_jkl);
Cconj = -2.0 * fn12 * fbp->p_cot1 * p_cot2 *
(1.0 + (SQR(cos_omega) - 1.0) * sin_ijk * sin_jkl);
CEconj1 = Cconj * (BOA_ij - 1.5e0);
CEconj2 = Cconj * (BOA_jk - 1.5e0);
CEconj3 = Cconj * (BOA_kl - 1.5e0);
CEconj4 = -fbp->p_cot1 * fn12 *
(SQR(cos_omega) - 1.0) * sin_jkl * tan_ijk_i;
CEconj5 = -fbp->p_cot1 * fn12 *
(SQR(cos_omega) - 1.0) * sin_ijk * tan_jkl_i;
CEconj6 = 2.0 * fbp->p_cot1 * fn12 *
cos_omega * sin_ijk * sin_jkl;
/* end 4-body conjugation energy */
/* forces */
bo_jk->Cdbopi += CEtors2;
workspace->CdDelta[j] += CEtors3;
workspace->CdDelta[k] += CEtors3;
bo_ij->Cdbo += (CEtors4 + CEconj1);
bo_jk->Cdbo += (CEtors5 + CEconj2);
bo_kl->Cdbo += (CEtors6 + CEconj3);
if( control->virial == 0 ) {
/* dcos_theta_ijk */
rvec_ScaledAdd( workspace->f[i],
CEtors7 + CEconj4, p_ijk->dcos_dk );
rvec_ScaledAdd( workspace->f[j],
CEtors7 + CEconj4, p_ijk->dcos_dj );
rvec_ScaledAdd( workspace->f[k],
CEtors7 + CEconj4, p_ijk->dcos_di );
/* dcos_theta_jkl */
rvec_ScaledAdd( workspace->f[j],
CEtors8 + CEconj5, p_jkl->dcos_di );
rvec_ScaledAdd( workspace->f[k],
CEtors8 + CEconj5, p_jkl->dcos_dj );
rvec_ScaledAdd( workspace->f[l],
CEtors8 + CEconj5, p_jkl->dcos_dk );
/* dcos_omega */
rvec_ScaledAdd( workspace->f[i],
CEtors9 + CEconj6, dcos_omega_di );
rvec_ScaledAdd( workspace->f[j],
CEtors9 + CEconj6, dcos_omega_dj );
rvec_ScaledAdd( workspace->f[k],
CEtors9 + CEconj6, dcos_omega_dk );
rvec_ScaledAdd( workspace->f[l],
CEtors9 + CEconj6, dcos_omega_dl );
}
else {
ivec_Sum(rel_box_jl, pbond_jk->rel_box, pbond_kl->rel_box);
/* dcos_theta_ijk */
rvec_Scale( force, CEtors7 + CEconj4, p_ijk->dcos_dk );
rvec_Add( workspace->f[i], force );
rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
rvec_ScaledAdd( workspace->f[j],
CEtors7 + CEconj4, p_ijk->dcos_dj );
rvec_Scale( force, CEtors7 + CEconj4, p_ijk->dcos_di );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, pbond_jk->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
/* dcos_theta_jkl */
rvec_ScaledAdd( workspace->f[j],
CEtors8 + CEconj5, p_jkl->dcos_di );
rvec_Scale( force, CEtors8 + CEconj5, p_jkl->dcos_dj );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, pbond_jk->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
rvec_Scale( force, CEtors8 + CEconj5, p_jkl->dcos_dk );
rvec_Add( workspace->f[l], force );
rvec_iMultiply( ext_press, rel_box_jl, force );
rvec_Add( data->my_ext_press, ext_press );
/* dcos_omega */
rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_di );
rvec_Add( workspace->f[i], force );
rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
rvec_ScaledAdd( workspace->f[j],
CEtors9 + CEconj6, dcos_omega_dj );
rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_dk );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, pbond_jk->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_dl );
rvec_Add( workspace->f[l], force );
rvec_iMultiply( ext_press, rel_box_jl, force );
rvec_Add( data->my_ext_press, ext_press );
}
#ifdef TEST_ENERGY
/* fprintf( out_control->etor,
"%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f\n",
r_ij, r_jk, r_kl, cos_ijk, cos_jkl, sin_ijk, sin_jkl );
fprintf( out_control->etor, "%12.8f\n", dfn11 ); */
/* fprintf( out_control->etor,
"%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f\n",
CEtors2, CEtors3, CEtors4, CEtors5, CEtors6,
CEtors7, CEtors8, CEtors9 ); */
/* fprintf( out_control->etor,
"%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f\n",
htra, htrb, htrc, hthd, hthe, hnra, hnrc, hnhd, hnhe ); */
/* fprintf( out_control->etor,
"%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f\n",
CEconj1, CEconj2, CEconj3, CEconj4, CEconj5, CEconj6 ); */
/* fprintf( out_control->etor, "%12.6f%12.6f%12.6f%12.6f\n",
fbp->V1, fbp->V2, fbp->V3, fbp->p_tor1 );*/
fprintf(out_control->etor,
//"%6d%6d%6d%6d%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%6d%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,system->my_atoms[l].orig_id,
RAD2DEG(omega), BOA_jk, e_tor, data->my_en.e_tor );
fprintf(out_control->econ,
//"%6d%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,system->my_atoms[l].orig_id,
RAD2DEG(omega), BOA_ij, BOA_jk, BOA_kl,
e_con, data->my_en.e_con );
#endif
#ifdef TEST_FORCES
/* Torsion Forces */
Add_dBOpinpi2( system, lists, j, pk, CEtors2, 0.0,
workspace->f_tor, workspace->f_tor );
Add_dDelta( system, lists, j, CEtors3, workspace->f_tor );
Add_dDelta( system, lists, k, CEtors3, workspace->f_tor );
Add_dBO( system, lists, j, pij, CEtors4, workspace->f_tor );
Add_dBO( system, lists, j, pk, CEtors5, workspace->f_tor );
Add_dBO( system, lists, k, plk, CEtors6, workspace->f_tor );
rvec_ScaledAdd( workspace->f_tor[i],
CEtors7, p_ijk->dcos_dk );
rvec_ScaledAdd( workspace->f_tor[j],
CEtors7, p_ijk->dcos_dj );
rvec_ScaledAdd( workspace->f_tor[k],
CEtors7, p_ijk->dcos_di );
rvec_ScaledAdd( workspace->f_tor[j],
CEtors8, p_jkl->dcos_di );
rvec_ScaledAdd( workspace->f_tor[k],
CEtors8, p_jkl->dcos_dj );
rvec_ScaledAdd( workspace->f_tor[l],
CEtors8, p_jkl->dcos_dk );
rvec_ScaledAdd( workspace->f_tor[i],
CEtors9, dcos_omega_di );
rvec_ScaledAdd( workspace->f_tor[j],
CEtors9, dcos_omega_dj );
rvec_ScaledAdd( workspace->f_tor[k],
CEtors9, dcos_omega_dk );
rvec_ScaledAdd( workspace->f_tor[l],
CEtors9, dcos_omega_dl );
/* Conjugation Forces */
Add_dBO( system, lists, j, pij, CEconj1, workspace->f_con );
Add_dBO( system, lists, j, pk, CEconj2, workspace->f_con );
Add_dBO( system, lists, k, plk, CEconj3, workspace->f_con );
rvec_ScaledAdd( workspace->f_con[i],
CEconj4, p_ijk->dcos_dk );
rvec_ScaledAdd( workspace->f_con[j],
CEconj4, p_ijk->dcos_dj );
rvec_ScaledAdd( workspace->f_con[k],
CEconj4, p_ijk->dcos_di );
rvec_ScaledAdd( workspace->f_con[j],
CEconj5, p_jkl->dcos_di );
rvec_ScaledAdd( workspace->f_con[k],
CEconj5, p_jkl->dcos_dj );
rvec_ScaledAdd( workspace->f_con[l],
CEconj5, p_jkl->dcos_dk );
rvec_ScaledAdd( workspace->f_con[i],
CEconj6, dcos_omega_di );
rvec_ScaledAdd( workspace->f_con[j],
CEconj6, dcos_omega_dj );
rvec_ScaledAdd( workspace->f_con[k],
CEconj6, dcos_omega_dk );
rvec_ScaledAdd( workspace->f_con[l],
CEconj6, dcos_omega_dl );
#endif
} // pl check ends
} // pl loop ends
} // pi check ends
} // pi loop ends
} // k-j neighbor check ends
} // j<k && j-k neighbor check ends
} // pk loop ends
} // j loop
#if defined(DEBUG)
fprintf( stderr, "Number of torsion angles: %d\n", num_frb_intrs );
fprintf( stderr, "Torsion Energy: %g\t Conjugation Energy: %g\n",
data->my_en.e_tor, data->my_en.e_con );
fprintf( stderr, "4body: ext_press (%12.6f %12.6f %12.6f)\n",
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
}

View File

@ -0,0 +1,30 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __TORSION_ANGLES_H_
#define __TORSION_ANGLES_H_
#include "reaxc_types.h"
void Torsion_Angles( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __TRAJ_H__
#define __TRAJ_H__
#include "reaxc_types.h"
#define MAX_TRJ_LINE_LEN 120
#define MAX_TRJ_BUFFER_SIZE (MAX_TRJ_LINE_LEN * 100)
#define NUM_HEADER_LINES 37
#define HEADER_LINE_LEN 62
#define STR_LINE "%-37s%-24s\n"
#define INT_LINE "%-37s%-24d\n"
#define INT2_LINE "%-36s%-12d,%-12d\n"
#define REAL_LINE "%-37s%-24.3f\n"
#define SCI_LINE "%-37s%-24g\n"
#define REAL3_LINE "%-32s%9.3f,%9.3f,%9.3f\n"
#define INIT_DESC "%9d%3d%9s%10.3f\n" //AtomID - AtomType, AtomName, AtomMass
#define INIT_DESC_LEN 32
#define SIZE_INFO_LINE2 "%-10d%-10d\n"
#define SIZE_INFO_LEN2 21
#define SIZE_INFO_LINE3 "%-10d%-10d%-10d\n"
#define SIZE_INFO_LEN3 31
#define ATOM_BASIC "%9d%10.3f%10.3f%10.3f%10.3f\n" //AtomID AtomType (X Y Z) Charge
#define ATOM_BASIC_LEN 50
#define ATOM_wV "%9d%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" //AtomID (X Y Z) (Vx Vy Vz) Charge
#define ATOM_wV_LEN 80
#define ATOM_wF "%9d%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" //AtomID (X Y Z) (Fx Fy Fz) Charge
#define ATOM_wF_LEN 80
#define ATOM_FULL "%9d%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f\n" //AtomID (X Y Z) (Vx Vy Vz) (Fx Fy Fz) Charge
#define ATOM_FULL_LEN 110
#define BOND_BASIC "%9d%9d%10.3f%10.3f\n" // Atom1 Atom2 Dist Total_BO
#define BOND_BASIC_LEN 39
#define BOND_FULL "%9d%9d%10.3f%10.3f%10.3f%10.3f%10.3f\n" // Atom1 Atom2 Dist Total_BO BOs BOpi BOpi2
#define BOND_FULL_LEN 69
#define ANGLE_BASIC "%9d%9d%9d%10.3f\n" // Atom1 Atom2 Atom3 Theta
#define ANGLE_BASIC_LEN 38
enum ATOM_LINE_OPTS { OPT_NOATOM = 0, OPT_ATOM_BASIC = 4, OPT_ATOM_wF = 5, OPT_ATOM_wV = 6, OPT_ATOM_FULL = 7, NR_OPT_ATOM = 8 };
enum BOND_LINE_OPTS { OPT_NOBOND, OPT_BOND_BASIC, OPT_BOND_FULL, NR_OPT_BOND };
enum ANGLE_LINE_OPTS { OPT_NOANGLE, OPT_ANGLE_BASIC, NR_OPT_ANGLE };
int Init_Traj( reax_system*, control_params*, output_controls*,
mpi_datatypes*, char* );
int End_Traj( int, output_controls* );
int Append_Frame( reax_system*, control_params*, simulation_data*,
reax_list**, output_controls*, mpi_datatypes* );
#endif

View File

@ -0,0 +1,977 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __REAX_TYPES_H_
#define __REAX_TYPES_H_
#include "ctype.h"
#include "math.h"
#include "mpi.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/time.h"
#include "time.h"
#include "zlib.h"
/************* SOME DEFS - crucial for reax_types.h *********/
//#define PURE_REAX
#define LAMMPS_REAX
//#define DEBUG
//#define DEBUG_FOCUS
//#define TEST_ENERGY
//#define TEST_FORCES
//#define CG_PERFORMANCE
#define LOG_PERFORMANCE
#define STANDARD_BOUNDARIES
//#define OLD_BOUNDARIES
//#define MIDPOINT_BOUNDARIES
#define REAX_MAX_STR 1024
#define REAX_MAX_NBRS 6
#define REAX_MAX_3BODY_PARAM 5
#define REAX_MAX_4BODY_PARAM 5
#define REAX_MAX_ATOM_TYPES 25
#define REAX_MAX_MOLECULE_SIZE 20
/********************** TYPE DEFINITIONS ********************/
typedef int ivec[3];
typedef double real;
typedef real rvec[3];
typedef real rtensor[3][3];
typedef real rvec2[2];
typedef real rvec4[4];
typedef struct {
int step, bigN;
real T, xi, v_xi, v_xi_old, G_xi;
rtensor box;
} restart_header;
typedef struct {
int orig_id, type;
char name[8];
rvec x, v;
} restart_atom;
typedef struct
{
int orig_id;
int imprt_id;
int type;
int num_bonds;
int num_hbonds;
//int pad; // pad to 8-byte address boundary
char name[8];
rvec x; // position
rvec v; // velocity
rvec f_old; // old force
rvec4 s, t; // for calculating q
} mpi_atom;
typedef struct
{
int orig_id;
int imprt_id;
int type;
int num_bonds;
int num_hbonds;
//int pad;
rvec x; // position
} boundary_atom;
typedef struct
{
//int ncells;
//int *cnt_by_gcell;
int cnt;
//int *block;
int *index;
//MPI_Datatype out_dtype;
void *out_atoms;
} mpi_out_data;
typedef struct
{
MPI_Comm world;
MPI_Comm comm_mesh3D;
MPI_Datatype sys_info;
MPI_Datatype mpi_atom_type;
MPI_Datatype boundary_atom_type;
MPI_Datatype mpi_rvec, mpi_rvec2;
MPI_Datatype restart_atom_type;
MPI_Datatype header_line;
MPI_Datatype header_view;
MPI_Datatype init_desc_line;
MPI_Datatype init_desc_view;
MPI_Datatype atom_line;
MPI_Datatype atom_view;
MPI_Datatype bond_line;
MPI_Datatype bond_view;
MPI_Datatype angle_line;
MPI_Datatype angle_view;
//MPI_Request send_req1[REAX_MAX_NBRS];
//MPI_Request send_req2[REAX_MAX_NBRS];
//MPI_Status send_stat1[REAX_MAX_NBRS];
//MPI_Status send_stat2[REAX_MAX_NBRS];
//MPI_Status recv_stat1[REAX_MAX_NBRS];
//MPI_Status recv_stat2[REAX_MAX_NBRS];
mpi_out_data out_buffers[REAX_MAX_NBRS];
void *in1_buffer;
void *in2_buffer;
} mpi_datatypes;
/* Global params mapping */
/*
l[0] = p_boc1
l[1] = p_boc2
l[2] = p_coa2
l[3] = N/A
l[4] = N/A
l[5] = N/A
l[6] = p_ovun6
l[7] = N/A
l[8] = p_ovun7
l[9] = p_ovun8
l[10] = N/A
l[11] = swa
l[12] = swb
l[13] = N/A
l[14] = p_val6
l[15] = p_lp1
l[16] = p_val9
l[17] = p_val10
l[18] = N/A
l[19] = p_pen2
l[20] = p_pen3
l[21] = p_pen4
l[22] = N/A
l[23] = p_tor2
l[24] = p_tor3
l[25] = p_tor4
l[26] = N/A
l[27] = p_cot2
l[28] = p_vdW1
l[29] = v_par30
l[30] = p_coa4
l[31] = p_ovun4
l[32] = p_ovun3
l[33] = p_val8
l[34] = N/A
l[35] = N/A
l[36] = N/A
l[37] = version number
l[38] = p_coa3
*/
typedef struct
{
int n_global;
real* l;
int vdw_type;
} global_parameters;
typedef struct
{
/* Line one in field file */
char name[15]; // Two character atom name
real r_s;
real valency; // Valency of the atom
real mass; // Mass of atom
real r_vdw;
real epsilon;
real gamma;
real r_pi;
real valency_e;
real nlp_opt;
/* Line two in field file */
real alpha;
real gamma_w;
real valency_boc;
real p_ovun5;
real chi;
real eta;
int p_hbond; // 1 for H, 2 for hbonding atoms (O,S,P,N), 0 for others
/* Line three in field file */
real r_pi_pi;
real p_lp2;
real b_o_131;
real b_o_132;
real b_o_133;
/* Line four in the field file */
real p_ovun2;
real p_val3;
real valency_val;
real p_val5;
real rcore2;
real ecore2;
real acore2;
} single_body_parameters;
/* Two Body Parameters */
typedef struct {
/* Bond Order parameters */
real p_bo1,p_bo2,p_bo3,p_bo4,p_bo5,p_bo6;
real r_s, r_p, r_pp; // r_o distances in BO formula
real p_boc3, p_boc4, p_boc5;
/* Bond Energy parameters */
real p_be1, p_be2;
real De_s, De_p, De_pp;
/* Over/Under coordination parameters */
real p_ovun1;
/* Van der Waal interaction parameters */
real D;
real alpha;
real r_vdW;
real gamma_w;
real rcore, ecore, acore;
/* electrostatic parameters */
real gamma; // note: this parameter is gamma^-3 and not gamma.
real v13cor, ovc;
} two_body_parameters;
/* 3-body parameters */
typedef struct {
/* valence angle */
real theta_00;
real p_val1, p_val2, p_val4, p_val7;
/* penalty */
real p_pen1;
/* 3-body conjugation */
real p_coa1;
} three_body_parameters;
typedef struct{
int cnt;
three_body_parameters prm[REAX_MAX_3BODY_PARAM];
} three_body_header;
/* hydrogen-bond parameters */
typedef struct{
real r0_hb, p_hb1, p_hb2, p_hb3;
} hbond_parameters;
/* 4-body parameters */
typedef struct {
real V1, V2, V3;
/* torsion angle */
real p_tor1;
/* 4-body conjugation */
real p_cot1;
} four_body_parameters;
typedef struct
{
int cnt;
four_body_parameters prm[REAX_MAX_4BODY_PARAM];
} four_body_header;
typedef struct
{
int num_atom_types;
global_parameters gp;
single_body_parameters *sbp;
two_body_parameters **tbp;
three_body_header ***thbp;
hbond_parameters ***hbp;
four_body_header ****fbp;
} reax_interaction;
typedef struct
{
int orig_id;
int imprt_id;
int type;
char name[8];
rvec x; // position
rvec v; // velocity
rvec f; // force
rvec f_old;
real q; // charge
rvec4 s; // they take part in
rvec4 t; // computing q
int Hindex;
int num_bonds;
int num_hbonds;
int renumber;
} reax_atom;
typedef struct
{
real V;
rvec min, max, box_norms;
rtensor box, box_inv;
rtensor trans, trans_inv;
rtensor g;
} simulation_box;
struct grid_cell
{
real cutoff;
rvec min, max;
ivec rel_box;
int mark;
int type;
int str;
int end;
int top;
int* atoms;
struct grid_cell** nbrs;
ivec* nbrs_x;
rvec* nbrs_cp;
};
typedef struct grid_cell grid_cell;
typedef struct
{
int total, max_atoms, max_nbrs;
ivec ncells;
rvec cell_len;
rvec inv_len;
ivec bond_span;
ivec nonb_span;
ivec vlist_span;
ivec native_cells;
ivec native_str;
ivec native_end;
real ghost_cut;
ivec ghost_span;
ivec ghost_nonb_span;
ivec ghost_hbond_span;
ivec ghost_bond_span;
grid_cell*** cells;
ivec *order;
} grid;
typedef struct
{
int rank;
int est_send, est_recv;
int atoms_str, atoms_cnt;
ivec rltv, prdc;
rvec bndry_min, bndry_max;
int send_type;
int recv_type;
ivec str_send;
ivec end_send;
ivec str_recv;
ivec end_recv;
} neighbor_proc;
typedef struct
{
int N;
int exc_gcells;
int exc_atoms;
} bound_estimate;
typedef struct
{
real ghost_nonb;
real ghost_hbond;
real ghost_bond;
real ghost_cutoff;
} boundary_cutoff;
typedef struct
{
reax_interaction reax_param;
int n, N, bigN, numH;
int local_cap, total_cap, gcell_cap, Hcap;
int est_recv, est_trans, max_recved;
int wsize, my_rank, num_nbrs;
ivec my_coords;
neighbor_proc my_nbrs[REAX_MAX_NBRS];
int *global_offset;
simulation_box big_box, my_box, my_ext_box;
grid my_grid;
boundary_cutoff bndry_cuts;
reax_atom *my_atoms;
} reax_system;
/* system control parameters */
typedef struct
{
char sim_name[REAX_MAX_STR];
int nprocs;
ivec procs_by_dim;
/* ensemble values:
0 : NVE
1 : bNVT (Berendsen)
2 : nhNVT (Nose-Hoover)
3 : sNPT (Parrinello-Rehman-Nose-Hoover) semiisotropic
4 : iNPT (Parrinello-Rehman-Nose-Hoover) isotropic
5 : NPT (Parrinello-Rehman-Nose-Hoover) Anisotropic*/
int ensemble;
int nsteps;
real dt;
int geo_format;
int restart;
int restrict_bonds;
int remove_CoM_vel;
int random_vel;
int reposition_atoms;
int reneighbor;
real vlist_cut;
real bond_cut;
real nonb_cut, nonb_low;
real hbond_cut;
real user_ghost_cut;
real bg_cut;
real bo_cut;
real thb_cut;
int tabulate;
int qeq_freq;
real q_err;
int refactor;
real droptol;
real T_init, T_final, T;
real Tau_T;
int T_mode;
real T_rate, T_freq;
int virial;
rvec P, Tau_P, Tau_PT;
int press_mode;
real compressibility;
int molecular_analysis;
int num_ignored;
int ignore[REAX_MAX_ATOM_TYPES];
int dipole_anal;
int freq_dipole_anal;
int diffusion_coef;
int freq_diffusion_coef;
int restrict_type;
} control_params;
typedef struct
{
real T;
real xi;
real v_xi;
real v_xi_old;
real G_xi;
} thermostat;
typedef struct
{
real P;
real eps;
real v_eps;
real v_eps_old;
real a_eps;
} isotropic_barostat;
typedef struct
{
rtensor P;
real P_scalar;
real eps;
real v_eps;
real v_eps_old;
real a_eps;
rtensor h0;
rtensor v_g0;
rtensor v_g0_old;
rtensor a_g0;
} flexible_barostat;
typedef struct
{
real start;
real end;
real elapsed;
real total;
real comm;
real nbrs;
real init_forces;
real bonded;
real nonb;
real qEq;
int s_matvecs;
int t_matvecs;
} reax_timing;
typedef struct
{
real e_tot;
real e_kin; // Total kinetic energy
real e_pot;
real e_bond; // Total bond energy
real e_ov; // Total over coordination
real e_un; // Total under coordination energy
real e_lp; // Total under coordination energy
real e_ang; // Total valance angle energy
real e_pen; // Total penalty energy
real e_coa; // Total three body conjgation energy
real e_hb; // Total Hydrogen bond energy
real e_tor; // Total torsional energy
real e_con; // Total four body conjugation energy
real e_vdW; // Total van der Waals energy
real e_ele; // Total electrostatics energy
real e_pol; // Polarization energy
} energy_data;
typedef struct
{
int step;
int prev_steps;
real time;
real M; // Total Mass
real inv_M; // 1 / Total Mass
rvec xcm; // Center of mass
rvec vcm; // Center of mass velocity
rvec fcm; // Center of mass force
rvec amcm; // Angular momentum of CoM
rvec avcm; // Angular velocity of CoM
real etran_cm; // Translational kinetic energy of CoM
real erot_cm; // Rotational kinetic energy of CoM
rtensor kinetic; // Kinetic energy tensor
rtensor virial; // Hydrodynamic virial
energy_data my_en;
energy_data sys_en;
real N_f; //Number of degrees of freedom
rvec t_scale;
rtensor p_scale;
thermostat therm; // Used in Nose_Hoover method
isotropic_barostat iso_bar;
flexible_barostat flex_bar;
real inv_W;
real kin_press;
rvec int_press;
rvec my_ext_press;
rvec ext_press;
rvec tot_press;
reax_timing timing;
} simulation_data;
typedef struct{
int thb;
int pthb; // pointer to the third body on the central atom's nbrlist
real theta, cos_theta;
rvec dcos_di, dcos_dj, dcos_dk;
} three_body_interaction_data;
typedef struct {
int nbr;
ivec rel_box;
real d;
rvec dvec;
} far_neighbor_data;
typedef struct {
int nbr;
int scl;
far_neighbor_data *ptr;
} hbond_data;
typedef struct{
int wrt;
rvec dVal;
} dDelta_data;
typedef struct{
int wrt;
rvec dBO, dBOpi, dBOpi2;
} dbond_data;
typedef struct{
real BO, BO_s, BO_pi, BO_pi2;
real Cdbo, Cdbopi, Cdbopi2;
real C1dbo, C2dbo, C3dbo;
real C1dbopi, C2dbopi, C3dbopi, C4dbopi;
real C1dbopi2, C2dbopi2, C3dbopi2, C4dbopi2;
rvec dBOp, dln_BOp_s, dln_BOp_pi, dln_BOp_pi2;
} bond_order_data;
typedef struct {
int nbr;
int sym_index;
int dbond_index;
ivec rel_box;
// rvec ext_factor;
real d;
rvec dvec;
bond_order_data bo_data;
} bond_data;
typedef struct {
int j;
real val;
} sparse_matrix_entry;
typedef struct {
int cap, n, m;
int *start, *end;
sparse_matrix_entry *entries;
} sparse_matrix;
typedef struct {
int num_far;
int H, Htop;
int hbonds, num_hbonds;
int bonds, num_bonds;
int num_3body;
int gcell_atoms;
} reallocate_data;
typedef struct
{
int allocated;
/* communication storage */
real *tmp_dbl[REAX_MAX_NBRS];
rvec *tmp_rvec[REAX_MAX_NBRS];
rvec2 *tmp_rvec2[REAX_MAX_NBRS];
int *within_bond_box;
/* bond order related storage */
real *total_bond_order;
real *Deltap, *Deltap_boc;
real *Delta, *Delta_lp, *Delta_lp_temp, *Delta_e, *Delta_boc;
real *dDelta_lp, *dDelta_lp_temp;
real *nlp, *nlp_temp, *Clp, *vlpex;
rvec *dDeltap_self;
int *bond_mark, *done_after;
/* QEq storage */
sparse_matrix *H, *L, *U;
real *Hdia_inv, *b_s, *b_t, *b_prc, *b_prm, *s, *t;
real *droptol;
rvec2 *b, *x;
/* GMRES storage */
real *y, *z, *g;
real *hc, *hs;
real **h, **v;
/* CG storage */
real *r, *d, *q, *p;
rvec2 *r2, *d2, *q2, *p2;
/* Taper */
real Tap[8]; //Tap7, Tap6, Tap5, Tap4, Tap3, Tap2, Tap1, Tap0;
/* storage for analysis */
int *mark, *old_mark;
rvec *x_old;
/* storage space for bond restrictions */
int *restricted;
int **restricted_list;
/* integrator */
rvec *v_const;
/* force calculations */
real *CdDelta; // coefficient of dDelta
rvec *f;
#ifdef TEST_FORCES
rvec *f_ele;
rvec *f_vdw;
rvec *f_bo;
rvec *f_be;
rvec *f_lp;
rvec *f_ov;
rvec *f_un;
rvec *f_ang;
rvec *f_coa;
rvec *f_pen;
rvec *f_hb;
rvec *f_tor;
rvec *f_con;
rvec *f_tot;
rvec *dDelta; // calculated on the fly in bond_orders.c together with bo'
int *rcounts;
int *displs;
int *id_all;
rvec *f_all;
#endif
reallocate_data realloc;
//int *num_bonds;
/* hydrogen bonds */
//int num_H, Hcap;
//int *Hindex;
//int *num_hbonds;
//int *hash;
//int *rev_hash;
} storage;
typedef union
{
void *v;
three_body_interaction_data *three_body_list;
bond_data *bond_list;
dbond_data *dbo_list;
dDelta_data *dDelta_list;
far_neighbor_data *far_nbr_list;
hbond_data *hbond_list;
} list_type;
typedef struct
{
int allocated;
int n;
int num_intrs;
int *index;
int *end_index;
int type;
list_type select;
} reax_list;
typedef struct
{
#if defined(PURE_REAX)
MPI_File trj;
#endif
FILE *strj;
int trj_offset;
int atom_line_len;
int bond_line_len;
int angle_line_len;
int write_atoms;
int write_bonds;
int write_angles;
char *line;
int buffer_len;
char *buffer;
FILE *out;
FILE *pot;
FILE *log;
FILE *mol, *ign;
FILE *dpl;
FILE *drft;
FILE *pdb;
FILE *prs;
int write_steps;
int traj_compress;
int traj_method;
char traj_title[81];
int atom_info;
int bond_info;
int angle_info;
int restart_format;
int restart_freq;
int debug_level;
int energy_update_freq;
#ifdef TEST_ENERGY
FILE *ebond;
FILE *elp, *eov, *eun;
FILE *eval, *epen, *ecoa;
FILE *ehb;
FILE *etor, *econ;
FILE *evdw, *ecou;
#endif
#ifdef TEST_FORCES
FILE *fbo, *fdbo;
FILE *fbond;
FILE *flp, *fov, *fun;
FILE *fang, *fcoa, *fpen;
FILE *fhb;
FILE *ftor, *fcon;
FILE *fvdw, *fele;
FILE *ftot, *fcomp;
#endif
#if defined(TEST_ENERGY) || defined(TEST_FORCES)
FILE *flist; // far neighbor list
FILE *blist; // bond list
FILE *nlist; // near neighbor list
#endif
} output_controls;
typedef struct
{
int atom_count;
int atom_list[REAX_MAX_MOLECULE_SIZE];
int mtypes[REAX_MAX_ATOM_TYPES];
} molecule;
typedef struct
{
real H;
real e_vdW, CEvd;
real e_ele, CEclmb;
} LR_data;
typedef struct
{
real a, b, c, d;
} cubic_spline_coef;
typedef struct
{
real xmin, xmax;
int n;
real dx, inv_dx;
real a;
real m;
real c;
LR_data *y;
cubic_spline_coef *H;
cubic_spline_coef *vdW, *CEvd;
cubic_spline_coef *ele, *CEclmb;
} LR_lookup_table;
extern LR_lookup_table **LR;
/* function pointer defs */
typedef void (*evolve_function)(reax_system*, control_params*,
simulation_data*, storage*, reax_list**,
output_controls*, mpi_datatypes* );
#if defined(PURE_REAX)
evolve_function Evolve;
#endif
typedef void (*interaction_function) (reax_system*, control_params*,
simulation_data*, storage*,
reax_list**, output_controls*);
typedef void (*print_interaction)(reax_system*, control_params*,
simulation_data*, storage*,
reax_list**, output_controls*);
typedef real (*lookup_function)(real);
typedef void (*message_sorter) (reax_system*, int, int, int, mpi_out_data*);
typedef void (*unpacker) ( reax_system*, int, void*, int, neighbor_proc*, int );
typedef void (*dist_packer) (void*, mpi_out_data*);
typedef void (*coll_unpacker) (void*, void*, mpi_out_data*);
#endif

View File

@ -0,0 +1,535 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "valence_angles.h"
#include "bond_orders.h"
#include "list.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_valence_angles.h"
#include "reaxc_bond_orders.h"
#include "reaxc_list.h"
#include "reaxc_vector.h"
#endif
/* calculates the theta angle between i-j-k */
void Calculate_Theta( rvec dvec_ji, real d_ji, rvec dvec_jk, real d_jk,
real *theta, real *cos_theta )
{
(*cos_theta) = Dot( dvec_ji, dvec_jk, 3 ) / ( d_ji * d_jk );
if( *cos_theta > 1. ) *cos_theta = 1.0;
if( *cos_theta < -1. ) *cos_theta = -1.0;
(*theta) = acos( *cos_theta );
}
/* calculates the derivative of the cosine of the angle between i-j-k */
void Calculate_dCos_Theta( rvec dvec_ji, real d_ji, rvec dvec_jk, real d_jk,
rvec* dcos_theta_di,
rvec* dcos_theta_dj,
rvec* dcos_theta_dk )
{
int t;
real sqr_d_ji = SQR(d_ji);
real sqr_d_jk = SQR(d_jk);
real inv_dists = 1.0 / (d_ji * d_jk);
real inv_dists3 = pow( inv_dists, 3 );
real dot_dvecs = Dot( dvec_ji, dvec_jk, 3 );
real Cdot_inv3 = dot_dvecs * inv_dists3;
for( t = 0; t < 3; ++t ) {
(*dcos_theta_di)[t] = dvec_jk[t] * inv_dists -
Cdot_inv3 * sqr_d_jk * dvec_ji[t];
(*dcos_theta_dj)[t] = -(dvec_jk[t] + dvec_ji[t]) * inv_dists +
Cdot_inv3 * ( sqr_d_jk * dvec_ji[t] + sqr_d_ji * dvec_jk[t] );
(*dcos_theta_dk)[t] = dvec_ji[t] * inv_dists -
Cdot_inv3 * sqr_d_ji * dvec_jk[t];
}
}
/* this is a 3-body interaction in which the main role is
played by j which sits in the middle of the other two. */
void Valence_Angles( reax_system *system, control_params *control,
simulation_data *data, storage *workspace,
reax_list **lists, output_controls *out_control )
{
int i, j, pi, k, pk, t;
int type_i, type_j, type_k;
int start_j, end_j, start_pk, end_pk;
int cnt, num_thb_intrs;
real temp, temp_bo_jt, pBOjt7;
real p_val1, p_val2, p_val3, p_val4, p_val5;
real p_val6, p_val7, p_val8, p_val9, p_val10;
real p_pen1, p_pen2, p_pen3, p_pen4;
real p_coa1, p_coa2, p_coa3, p_coa4;
real trm8, expval6, expval7, expval2theta, expval12theta, exp3ij, exp3jk;
real exp_pen2ij, exp_pen2jk, exp_pen3, exp_pen4, trm_pen34, exp_coa2;
real dSBO1, dSBO2, SBO, SBO2, CSBO2, SBOp, prod_SBO, vlpadj;
real CEval1, CEval2, CEval3, CEval4, CEval5, CEval6, CEval7, CEval8;
real CEpen1, CEpen2, CEpen3;
real e_ang, e_coa, e_pen;
real CEcoa1, CEcoa2, CEcoa3, CEcoa4, CEcoa5;
real Cf7ij, Cf7jk, Cf8j, Cf9j;
real f7_ij, f7_jk, f8_Dj, f9_Dj;
real Ctheta_0, theta_0, theta_00, theta, cos_theta, sin_theta;
real r_ij, r_jk;
real BOA_ij, BOA_jk;
rvec force, ext_press;
// rtensor temp_rtensor, total_rtensor;
three_body_header *thbh;
three_body_parameters *thbp;
three_body_interaction_data *p_ijk, *p_kji;
bond_data *pbond_ij, *pbond_jk, *pbond_jt;
bond_order_data *bo_ij, *bo_jk, *bo_jt;
reax_list *bonds = (*lists) + BONDS;
reax_list *thb_intrs = (*lists) + THREE_BODIES;
/* global parameters used in these calculations */
p_val6 = system->reax_param.gp.l[14];
p_val8 = system->reax_param.gp.l[33];
p_val9 = system->reax_param.gp.l[16];
p_val10 = system->reax_param.gp.l[17];
num_thb_intrs = 0;
for( j = 0; j < system->N; ++j ) {
// fprintf( out_control->eval, "j: %d\n", j );
type_j = system->my_atoms[j].type;
start_j = Start_Index(j, bonds);
end_j = End_Index(j, bonds);
p_val3 = system->reax_param.sbp[ type_j ].p_val3;
p_val5 = system->reax_param.sbp[ type_j ].p_val5;
SBOp = 0, prod_SBO = 1;
for( t = start_j; t < end_j; ++t ) {
bo_jt = &(bonds->select.bond_list[t].bo_data);
SBOp += (bo_jt->BO_pi + bo_jt->BO_pi2);
temp = SQR( bo_jt->BO );
temp *= temp;
temp *= temp;
prod_SBO *= exp( -temp );
}
/* modifications to match Adri's code - 09/01/09 */
if( workspace->vlpex[j] >= 0 ){
vlpadj = 0;
dSBO2 = prod_SBO - 1;
}
else{
vlpadj = workspace->nlp[j];
dSBO2 = (prod_SBO - 1) * (1 - p_val8 * workspace->dDelta_lp[j]);
}
SBO = SBOp + (1 - prod_SBO) * (-workspace->Delta_boc[j] - p_val8 * vlpadj);
dSBO1 = -8 * prod_SBO * ( workspace->Delta_boc[j] + p_val8 * vlpadj );
if( SBO <= 0 )
SBO2 = 0, CSBO2 = 0;
else if( SBO > 0 && SBO <= 1 ) {
SBO2 = pow( SBO, p_val9 );
CSBO2 = p_val9 * pow( SBO, p_val9 - 1 );
}
else if( SBO > 1 && SBO < 2 ) {
SBO2 = 2 - pow( 2-SBO, p_val9 );
CSBO2 = p_val9 * pow( 2 - SBO, p_val9 - 1 );
}
else
SBO2 = 2, CSBO2 = 0;
expval6 = exp( p_val6 * workspace->Delta_boc[j] );
for( pi = start_j; pi < end_j; ++pi ) {
Set_Start_Index( pi, num_thb_intrs, thb_intrs );
pbond_ij = &(bonds->select.bond_list[pi]);
bo_ij = &(pbond_ij->bo_data);
BOA_ij = bo_ij->BO - control->thb_cut;
if( BOA_ij/*bo_ij->BO*/ > 0.0 &&
( j < system->n || pbond_ij->nbr < system->n ) ) {
i = pbond_ij->nbr;
r_ij = pbond_ij->d;
type_i = system->my_atoms[i].type;
// fprintf( out_control->eval, "i: %d\n", i );
/* first copy 3-body intrs from previously computed ones where i>k.
in the second for-loop below,
we compute only new 3-body intrs where i < k */
for( pk = start_j; pk < pi; ++pk ) {
// fprintf( out_control->eval, "pk: %d\n", pk );
start_pk = Start_Index( pk, thb_intrs );
end_pk = End_Index( pk, thb_intrs );
for( t = start_pk; t < end_pk; ++t )
if( thb_intrs->select.three_body_list[t].thb == i ) {
p_ijk = &(thb_intrs->select.three_body_list[num_thb_intrs] );
p_kji = &(thb_intrs->select.three_body_list[t]);
p_ijk->thb = bonds->select.bond_list[pk].nbr;
p_ijk->pthb = pk;
p_ijk->theta = p_kji->theta;
rvec_Copy( p_ijk->dcos_di, p_kji->dcos_dk );
rvec_Copy( p_ijk->dcos_dj, p_kji->dcos_dj );
rvec_Copy( p_ijk->dcos_dk, p_kji->dcos_di );
++num_thb_intrs;
break;
}
}
/* and this is the second for loop mentioned above */
for( pk = pi+1; pk < end_j; ++pk ) {
pbond_jk = &(bonds->select.bond_list[pk]);
bo_jk = &(pbond_jk->bo_data);
BOA_jk = bo_jk->BO - control->thb_cut;
k = pbond_jk->nbr;
type_k = system->my_atoms[k].type;
p_ijk = &( thb_intrs->select.three_body_list[num_thb_intrs] );
Calculate_Theta( pbond_ij->dvec, pbond_ij->d,
pbond_jk->dvec, pbond_jk->d,
&theta, &cos_theta );
Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d,
pbond_jk->dvec, pbond_jk->d,
&(p_ijk->dcos_di), &(p_ijk->dcos_dj),
&(p_ijk->dcos_dk) );
p_ijk->thb = k;
p_ijk->pthb = pk;
p_ijk->theta = theta;
sin_theta = sin( theta );
if( sin_theta < 1.0e-5 )
sin_theta = 1.0e-5;
++num_thb_intrs;
if( (j < system->n) && (BOA_jk > 0.0) &&
(bo_ij->BO * bo_jk->BO > SQR(control->thb_cut)/*0*/) ) {
r_jk = pbond_jk->d;
thbh = &( system->reax_param.thbp[ type_i ][ type_j ][ type_k ] );
/* if( system->my_atoms[i].orig_id < system->my_atoms[k].orig_id )
fprintf( fval, "%6d %6d %6d %7.3f %7.3f %7.3f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
bo_ij->BO, bo_jk->BO, p_ijk->theta );
else
fprintf( fval, "%6d %6d %6d %7.3f %7.3f %7.3f\n",
system->my_atoms[k].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[i].orig_id,
bo_jk->BO, bo_ij->BO, p_ijk->theta ); */
for( cnt = 0; cnt < thbh->cnt; ++cnt ) {
// fprintf( out_control->eval, "%6d%6d%6d -- exists in thbp\n",
// i+1, j+1, k+1 );
if( fabs(thbh->prm[cnt].p_val1) > 0.001 ) {
thbp = &( thbh->prm[cnt] );
/* ANGLE ENERGY */
p_val1 = thbp->p_val1;
p_val2 = thbp->p_val2;
p_val4 = thbp->p_val4;
p_val7 = thbp->p_val7;
theta_00 = thbp->theta_00;
exp3ij = exp( -p_val3 * pow( BOA_ij, p_val4 ) );
f7_ij = 1.0 - exp3ij;
Cf7ij = p_val3 * p_val4 * pow( BOA_ij, p_val4 - 1.0 ) * exp3ij;
exp3jk = exp( -p_val3 * pow( BOA_jk, p_val4 ) );
f7_jk = 1.0 - exp3jk;
Cf7jk = p_val3 * p_val4 * pow( BOA_jk, p_val4 - 1.0 ) * exp3jk;
expval7 = exp( -p_val7 * workspace->Delta_boc[j] );
trm8 = 1.0 + expval6 + expval7;
f8_Dj = p_val5 - ( (p_val5 - 1.0) * (2.0 + expval6) / trm8 );
Cf8j = ( (1.0 - p_val5) / SQR(trm8) ) *
( p_val6 * expval6 * trm8 -
(2.0 + expval6) * ( p_val6*expval6 - p_val7*expval7 ) );
theta_0 = 180.0 - theta_00 * (1.0 -
exp(-p_val10 * (2.0 - SBO2)));
theta_0 = DEG2RAD( theta_0 );
expval2theta = exp( -p_val2 * SQR(theta_0 - theta) );
if( p_val1 >= 0 )
expval12theta = p_val1 * (1.0 - expval2theta);
else // To avoid linear Me-H-Me angles (6/6/06)
expval12theta = p_val1 * -expval2theta;
CEval1 = Cf7ij * f7_jk * f8_Dj * expval12theta;
CEval2 = Cf7jk * f7_ij * f8_Dj * expval12theta;
CEval3 = Cf8j * f7_ij * f7_jk * expval12theta;
CEval4 = -2.0 * p_val1 * p_val2 * f7_ij * f7_jk * f8_Dj *
expval2theta * (theta_0 - theta);
Ctheta_0 = p_val10 * DEG2RAD(theta_00) *
exp( -p_val10 * (2.0 - SBO2) );
CEval5 = -CEval4 * Ctheta_0 * CSBO2;
CEval6 = CEval5 * dSBO1;
CEval7 = CEval5 * dSBO2;
CEval8 = -CEval4 / sin_theta;
data->my_en.e_ang += e_ang =
f7_ij * f7_jk * f8_Dj * expval12theta;
/* END ANGLE ENERGY*/
/* PENALTY ENERGY */
p_pen1 = thbp->p_pen1;
p_pen2 = system->reax_param.gp.l[19];
p_pen3 = system->reax_param.gp.l[20];
p_pen4 = system->reax_param.gp.l[21];
exp_pen2ij = exp( -p_pen2 * SQR( BOA_ij - 2.0 ) );
exp_pen2jk = exp( -p_pen2 * SQR( BOA_jk - 2.0 ) );
exp_pen3 = exp( -p_pen3 * workspace->Delta[j] );
exp_pen4 = exp( p_pen4 * workspace->Delta[j] );
trm_pen34 = 1.0 + exp_pen3 + exp_pen4;
f9_Dj = ( 2.0 + exp_pen3 ) / trm_pen34;
Cf9j = ( -p_pen3 * exp_pen3 * trm_pen34 -
(2.0 + exp_pen3) * ( -p_pen3 * exp_pen3 +
p_pen4 * exp_pen4 ) ) /
SQR( trm_pen34 );
data->my_en.e_pen += e_pen =
p_pen1 * f9_Dj * exp_pen2ij * exp_pen2jk;
CEpen1 = e_pen * Cf9j / f9_Dj;
temp = -2.0 * p_pen2 * e_pen;
CEpen2 = temp * (BOA_ij - 2.0);
CEpen3 = temp * (BOA_jk - 2.0);
/* END PENALTY ENERGY */
/* COALITION ENERGY */
p_coa1 = thbp->p_coa1;
p_coa2 = system->reax_param.gp.l[2];
p_coa3 = system->reax_param.gp.l[38];
p_coa4 = system->reax_param.gp.l[30];
exp_coa2 = exp( p_coa2 * workspace->Delta_boc[j] );
data->my_en.e_coa += e_coa =
p_coa1 / (1. + exp_coa2) *
exp( -p_coa3 * SQR(workspace->total_bond_order[i]-BOA_ij) ) *
exp( -p_coa3 * SQR(workspace->total_bond_order[k]-BOA_jk) ) *
exp( -p_coa4 * SQR(BOA_ij - 1.5) ) *
exp( -p_coa4 * SQR(BOA_jk - 1.5) );
CEcoa1 = -2 * p_coa4 * (BOA_ij - 1.5) * e_coa;
CEcoa2 = -2 * p_coa4 * (BOA_jk - 1.5) * e_coa;
CEcoa3 = -p_coa2 * exp_coa2 * e_coa / (1 + exp_coa2);
CEcoa4 = -2 * p_coa3 *
(workspace->total_bond_order[i]-BOA_ij) * e_coa;
CEcoa5 = -2 * p_coa3 *
(workspace->total_bond_order[k]-BOA_jk) * e_coa;
/* END COALITION ENERGY */
/* FORCES */
bo_ij->Cdbo += (CEval1 + CEpen2 + (CEcoa1 - CEcoa4));
bo_jk->Cdbo += (CEval2 + CEpen3 + (CEcoa2 - CEcoa5));
workspace->CdDelta[j] += ((CEval3 + CEval7) + CEpen1 + CEcoa3);
workspace->CdDelta[i] += CEcoa4;
workspace->CdDelta[k] += CEcoa5;
for( t = start_j; t < end_j; ++t ) {
pbond_jt = &( bonds->select.bond_list[t] );
bo_jt = &(pbond_jt->bo_data);
temp_bo_jt = bo_jt->BO;
temp = CUBE( temp_bo_jt );
pBOjt7 = temp * temp * temp_bo_jt;
// fprintf( out_control->eval, "%6d%12.8f\n",
// workspace->reverse_map[bonds->select.bond_list[t].nbr],
// (CEval6 * pBOjt7) );
bo_jt->Cdbo += (CEval6 * pBOjt7);
bo_jt->Cdbopi += CEval5;
bo_jt->Cdbopi2 += CEval5;
}
if( control->virial == 0 ) {
rvec_ScaledAdd( workspace->f[i], CEval8, p_ijk->dcos_di );
rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj );
rvec_ScaledAdd( workspace->f[k], CEval8, p_ijk->dcos_dk );
}
else {
/* terms not related to bond order derivatives are
added directly into forces and pressure vector/tensor */
rvec_Scale( force, CEval8, p_ijk->dcos_di );
rvec_Add( workspace->f[i], force );
rvec_iMultiply( ext_press, pbond_ij->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj );
rvec_Scale( force, CEval8, p_ijk->dcos_dk );
rvec_Add( workspace->f[k], force );
rvec_iMultiply( ext_press, pbond_jk->rel_box, force );
rvec_Add( data->my_ext_press, ext_press );
}
#ifdef TEST_ENERGY
/*fprintf( out_control->eval, "%12.8f%12.8f%12.8f%12.8f\n",
p_val3, p_val4, BOA_ij, BOA_jk );
fprintf(out_control->eval, "%13.8f%13.8f%13.8f%13.8f%13.8f\n",
workspace->Delta_e[j], workspace->vlpex[j],
dSBO1, dSBO2, vlpadj );
fprintf( out_control->eval, "%12.8f%12.8f%12.8f%12.8f\n",
f7_ij, f7_jk, f8_Dj, expval12theta );
fprintf( out_control->eval,
"%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f%12.8f\n",
CEval1, CEval2, CEval3, CEval4,
CEval5, CEval6, CEval7, CEval8 );
fprintf( out_control->eval,
"%12.8f%12.8f%12.8f\n%12.8f%12.8f%12.8f\n%12.8f%12.8f%12.8f\n",
p_ijk->dcos_di[0]/sin_theta, p_ijk->dcos_di[1]/sin_theta,
p_ijk->dcos_di[2]/sin_theta,
p_ijk->dcos_dj[0]/sin_theta, p_ijk->dcos_dj[1]/sin_theta,
p_ijk->dcos_dj[2]/sin_theta,
p_ijk->dcos_dk[0]/sin_theta, p_ijk->dcos_dk[1]/sin_theta,
p_ijk->dcos_dk[2]/sin_theta);
fprintf( out_control->eval,
"%6d%6d%6d%15.8f%15.8f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
RAD2DEG(theta), e_ang );*/
fprintf( out_control->eval,
//"%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
RAD2DEG(theta), theta_0, BOA_ij, BOA_jk,
e_ang, data->my_en.e_ang );
fprintf( out_control->epen,
//"%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
RAD2DEG(theta), BOA_ij, BOA_jk, e_pen,
data->my_en.e_pen );
fprintf( out_control->ecoa,
//"%6d%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
"%6d%6d%6d%12.4f%12.4f%12.4f%12.4f%12.4f\n",
system->my_atoms[i].orig_id,
system->my_atoms[j].orig_id,
system->my_atoms[k].orig_id,
RAD2DEG(theta), BOA_ij, BOA_jk,
e_coa, data->my_en.e_coa );
#endif
#ifdef TEST_FORCES /* angle forces */
Add_dBO( system, lists, j, pi, CEval1, workspace->f_ang );
Add_dBO( system, lists, j, pk, CEval2, workspace->f_ang );
Add_dDelta( system, lists, j,
CEval3 + CEval7, workspace->f_ang );
for( t = start_j; t < end_j; ++t ) {
pbond_jt = &( bonds->select.bond_list[t] );
bo_jt = &(pbond_jt->bo_data);
temp_bo_jt = bo_jt->BO;
temp = CUBE( temp_bo_jt );
pBOjt7 = temp * temp * temp_bo_jt;
Add_dBO( system, lists, j, t, pBOjt7 * CEval6,
workspace->f_ang );
Add_dBOpinpi2( system, lists, j, t, CEval5, CEval5,
workspace->f_ang, workspace->f_ang );
}
rvec_ScaledAdd( workspace->f_ang[i], CEval8, p_ijk->dcos_di );
rvec_ScaledAdd( workspace->f_ang[j], CEval8, p_ijk->dcos_dj );
rvec_ScaledAdd( workspace->f_ang[k], CEval8, p_ijk->dcos_dk );
/* end angle forces */
/* penalty forces */
Add_dDelta( system, lists, j, CEpen1, workspace->f_pen );
Add_dBO( system, lists, j, pi, CEpen2, workspace->f_pen );
Add_dBO( system, lists, j, pk, CEpen3, workspace->f_pen );
/* end penalty forces */
/* coalition forces */
Add_dBO( system, lists, j, pi, CEcoa1 - CEcoa4,
workspace->f_coa );
Add_dBO( system, lists, j, pk, CEcoa2 - CEcoa5,
workspace->f_coa );
Add_dDelta( system, lists, j, CEcoa3, workspace->f_coa );
Add_dDelta( system, lists, i, CEcoa4, workspace->f_coa );
Add_dDelta( system, lists, k, CEcoa5, workspace->f_coa );
/* end coalition forces */
#endif
}
}
}
}
}
Set_End_Index(pi, num_thb_intrs, thb_intrs );
}
}
if( num_thb_intrs >= thb_intrs->num_intrs * DANGER_ZONE ) {
workspace->realloc.num_3body = num_thb_intrs;
if( num_thb_intrs > thb_intrs->num_intrs ) {
fprintf( stderr, "step%d-ran out of space on angle_list: top=%d, max=%d",
data->step, num_thb_intrs, thb_intrs->num_intrs );
MPI_Abort( MPI_COMM_WORLD, INSUFFICIENT_MEMORY );
}
}
//fprintf( stderr,"%d: Number of angle interactions: %d\n",
// data->step, num_thb_intrs );
#if defined(DEBUG)
fprintf( stderr, "Number of angle interactions: %d\n", num_thb_intrs );
fprintf( stderr,
"Angle Energy: %g\t Penalty Energy: %g\t Coalition Energy: %g\t\n",
data->my_en.e_ang, data->my_en.e_pen, data->my_en.e_coa );
fprintf( stderr, "3body: ext_press (%12.6f %12.6f %12.6f)\n",
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
}

View File

@ -0,0 +1,34 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __VALENCE_ANGLES_H_
#define __VALENCE_ANGLES_H_
#include "reaxc_types.h"
void Valence_Angles( reax_system*, control_params*, simulation_data*,
storage*, reax_list**, output_controls* );
void Calculate_Theta( rvec, real, rvec, real, real*, real* );
void Calculate_dCos_Theta( rvec, real, rvec, real, rvec*, rvec*, rvec* );
#endif

View File

@ -0,0 +1,518 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reaxc_types.h"
#if defined(PURE_REAX)
#include "vector.h"
#include "random.h"
#elif defined(LAMMPS_REAX)
#include "reaxc_vector.h"
#endif
int Vector_isZero( real* v, int k )
{
for( --k; k>=0; --k )
if( fabs( v[k] ) > ALMOST_ZERO )
return 0;
return 1;
}
void Vector_MakeZero( real *v, int k )
{
for( --k; k>=0; --k )
v[k] = 0;
}
void Vector_Copy( real* dest, real* v, int k )
{
for( --k; k>=0; --k )
dest[k] = v[k];
}
void Vector_Scale( real* dest, real c, real* v, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k];
}
void Vector_Sum( real* dest, real c, real* v, real d, real* y, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k] + d * y[k];
}
void Vector_Add( real* dest, real c, real* v, int k )
{
for( --k; k>=0; --k )
dest[k] += c * v[k];
}
real Dot( real* v1, real* v2, int k )
{
real ret = 0;
for( --k; k>=0; --k )
ret += v1[k] * v2[k];
return ret;
}
real Norm( real* v1, int k )
{
real ret = 0;
for( --k; k>=0; --k )
ret += SQR( v1[k] );
return sqrt( ret );
}
void Vector_Print( FILE *fout, char *vname, real *v, int k )
{
int i;
fprintf( fout, "%s:", vname );
for( i = 0; i < k; ++i )
fprintf( fout, "%24.15e\n", v[i] );
fprintf( fout, "\n" );
}
void rvec_Copy( rvec dest, rvec src )
{
dest[0] = src[0], dest[1] = src[1], dest[2] = src[2];
}
void rvec_Scale( rvec ret, real c, rvec v )
{
ret[0] = c * v[0], ret[1] = c * v[1], ret[2] = c * v[2];
}
void rvec_Add( rvec ret, rvec v )
{
ret[0] += v[0], ret[1] += v[1], ret[2] += v[2];
}
void rvec_ScaledAdd( rvec ret, real c, rvec v )
{
ret[0] += c * v[0], ret[1] += c * v[1], ret[2] += c * v[2];
}
void rvec_Sum( rvec ret, rvec v1 ,rvec v2 )
{
ret[0] = v1[0] + v2[0];
ret[1] = v1[1] + v2[1];
ret[2] = v1[2] + v2[2];
}
void rvec_ScaledSum( rvec ret, real c1, rvec v1 ,real c2, rvec v2 )
{
ret[0] = c1 * v1[0] + c2 * v2[0];
ret[1] = c1 * v1[1] + c2 * v2[1];
ret[2] = c1 * v1[2] + c2 * v2[2];
}
real rvec_Dot( rvec v1, rvec v2 )
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
real rvec_ScaledDot( real c1, rvec v1, real c2, rvec v2 )
{
return (c1*c2) * (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
}
void rvec_Multiply( rvec r, rvec v1, rvec v2 )
{
r[0] = v1[0] * v2[0];
r[1] = v1[1] * v2[1];
r[2] = v1[2] * v2[2];
}
void rvec_iMultiply( rvec r, ivec v1, rvec v2 )
{
r[0] = v1[0] * v2[0];
r[1] = v1[1] * v2[1];
r[2] = v1[2] * v2[2];
}
void rvec_Divide( rvec r, rvec v1, rvec v2 )
{
r[0] = v1[0] / v2[0];
r[1] = v1[1] / v2[1];
r[2] = v1[2] / v2[2];
}
void rvec_iDivide( rvec r, rvec v1, ivec v2 )
{
r[0] = v1[0] / v2[0];
r[1] = v1[1] / v2[1];
r[2] = v1[2] / v2[2];
}
void rvec_Invert( rvec r, rvec v )
{
r[0] = 1. / v[0];
r[1] = 1. / v[1];
r[2] = 1. / v[2];
}
void rvec_Cross( rvec ret, rvec v1, rvec v2 )
{
ret[0] = v1[1] * v2[2] - v1[2] * v2[1];
ret[1] = v1[2] * v2[0] - v1[0] * v2[2];
ret[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
void rvec_OuterProduct( rtensor r, rvec v1, rvec v2 )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
r[i][j] = v1[i] * v2[j];
}
real rvec_Norm_Sqr( rvec v )
{
return SQR(v[0]) + SQR(v[1]) + SQR(v[2]);
}
real rvec_Norm( rvec v )
{
return sqrt( SQR(v[0]) + SQR(v[1]) + SQR(v[2]) );
}
int rvec_isZero( rvec v )
{
if( fabs(v[0]) > ALMOST_ZERO ||
fabs(v[1]) > ALMOST_ZERO ||
fabs(v[2]) > ALMOST_ZERO )
return 0;
return 1;
}
void rvec_MakeZero( rvec v )
{
// v[0] = v[1] = v[2] = 0.0000000000000;
v[0] = v[1] = v[2] = 0.000000000000000e+00;
}
#if defined(PURE_REAX)
void rvec_Random( rvec v )
{
v[0] = Random(2.0)-1.0;
v[1] = Random(2.0)-1.0;
v[2] = Random(2.0)-1.0;
}
#endif
void rtensor_Multiply( rtensor ret, rtensor m1, rtensor m2 )
{
int i, j, k;
rtensor temp;
// check if the result matrix is the same as one of m1, m2.
// if so, we cannot modify the contents of m1 or m2, so
// we have to use a temp matrix.
if( ret == m1 || ret == m2 )
{
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
{
temp[i][j] = 0;
for( k = 0; k < 3; ++k )
temp[i][j] += m1[i][k] * m2[k][j];
}
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] = temp[i][j];
}
else
{
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
{
ret[i][j] = 0;
for( k = 0; k < 3; ++k )
ret[i][j] += m1[i][k] * m2[k][j];
}
}
}
void rtensor_MatVec( rvec ret, rtensor m, rvec v )
{
int i;
rvec temp;
// if ret is the same vector as v, we cannot modify the
// contents of v until all computation is finished.
if( ret == v )
{
for( i = 0; i < 3; ++i )
temp[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][2] * v[2];
for( i = 0; i < 3; ++i )
ret[i] = temp[i];
}
else
{
for( i = 0; i < 3; ++i )
ret[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][2] * v[2];
}
}
void rtensor_Scale( rtensor ret, real c, rtensor m )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] = c * m[i][j];
}
void rtensor_Add( rtensor ret, rtensor t )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] += t[i][j];
}
void rtensor_ScaledAdd( rtensor ret, real c, rtensor t )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] += c * t[i][j];
}
void rtensor_Sum( rtensor ret, rtensor t1, rtensor t2 )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] = t1[i][j] + t2[i][j];
}
void rtensor_ScaledSum( rtensor ret, real c1, rtensor t1,
real c2, rtensor t2 )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] = c1 * t1[i][j] + c2 * t2[i][j];
}
void rtensor_Copy( rtensor ret, rtensor t )
{
int i, j;
for( i = 0; i < 3; ++i )
for( j = 0; j < 3; ++j )
ret[i][j] = t[i][j];
}
void rtensor_Identity( rtensor t )
{
t[0][0] = t[1][1] = t[2][2] = 1;
t[0][1] = t[0][2] = t[1][0] = t[1][2] = t[2][0] = t[2][1] = 0;
}
void rtensor_MakeZero( rtensor t )
{
t[0][0] = t[0][1] = t[0][2] = 0;
t[1][0] = t[1][1] = t[1][2] = 0;
t[2][0] = t[2][1] = t[2][2] = 0;
}
void rtensor_Transpose( rtensor ret, rtensor t )
{
ret[0][0] = t[0][0], ret[1][1] = t[1][1], ret[2][2] = t[2][2];
ret[0][1] = t[1][0], ret[0][2] = t[2][0];
ret[1][0] = t[0][1], ret[1][2] = t[2][1];
ret[2][0] = t[0][2], ret[2][1] = t[1][2];
}
real rtensor_Det( rtensor t )
{
return ( t[0][0] * (t[1][1] * t[2][2] - t[1][2] * t[2][1] ) +
t[0][1] * (t[1][2] * t[2][0] - t[1][0] * t[2][2] ) +
t[0][2] * (t[1][0] * t[2][1] - t[1][1] * t[2][0] ) );
}
real rtensor_Trace( rtensor t )
{
return (t[0][0] + t[1][1] + t[2][2]);
}
void Print_rTensor(FILE* fp, rtensor t)
{
int i, j;
for (i=0; i < 3; i++)
{
fprintf(fp,"[");
for (j=0; j < 3; j++)
fprintf(fp,"%8.3f,\t",t[i][j]);
fprintf(fp,"]\n");
}
}
void ivec_MakeZero( ivec v )
{
v[0] = v[1] = v[2] = 0;
}
void ivec_Copy( ivec dest, ivec src )
{
dest[0] = src[0], dest[1] = src[1], dest[2] = src[2];
}
void ivec_Scale( ivec dest, real C, ivec src )
{
dest[0] = (int)(C * src[0]);
dest[1] = (int)(C * src[1]);
dest[2] = (int)(C * src[2]);
}
void ivec_rScale( ivec dest, real C, rvec src )
{
dest[0] = (int)(C * src[0]);
dest[1] = (int)(C * src[1]);
dest[2] = (int)(C * src[2]);
}
int ivec_isZero( ivec v )
{
if( v[0]==0 && v[1]==0 && v[2]==0 )
return 1;
return 0;
}
int ivec_isEqual( ivec v1, ivec v2 )
{
if( v1[0]==v2[0] && v1[1]==v2[1] && v1[2]==v2[2] )
return 1;
return 0;
}
void ivec_Sum( ivec dest, ivec v1, ivec v2 )
{
dest[0] = v1[0] + v2[0];
dest[1] = v1[1] + v2[1];
dest[2] = v1[2] + v2[2];
}
void ivec_ScaledSum( ivec dest, int k1, ivec v1, int k2, ivec v2 )
{
dest[0] = k1*v1[0] + k2*v2[0];
dest[1] = k1*v1[1] + k2*v2[1];
dest[2] = k1*v1[2] + k2*v2[2];
}
void ivec_Add( ivec dest, ivec v )
{
dest[0] += v[0];
dest[1] += v[1];
dest[2] += v[2];
}
void ivec_ScaledAdd( ivec dest, int k, ivec v )
{
dest[0] += k * v[0];
dest[1] += k * v[1];
dest[2] += k * v[2];
}
void ivec_Max( ivec res, ivec v1, ivec v2 )
{
res[0] = MAX( v1[0], v2[0] );
res[1] = MAX( v1[1], v2[1] );
res[2] = MAX( v1[2], v2[2] );
}
void ivec_Max3( ivec res, ivec v1, ivec v2, ivec v3 )
{
res[0] = MAX3( v1[0], v2[0], v3[0] );
res[1] = MAX3( v1[1], v2[1], v3[1] );
res[2] = MAX3( v1[2], v2[2], v3[2] );
}

View File

@ -0,0 +1,89 @@
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#ifndef __VECTOR_H_
#define __VECTOR_H_
#include "reaxc_types.h"
#include "reaxc_defs.h"
int Vector_isZero( real*, int );
void Vector_MakeZero( real*, int );
void Vector_Copy( real*, real*, int );
void Vector_Scale( real*, real, real*, int );
void Vector_Sum( real*, real, real*, real, real*, int );
void Vector_Add( real*, real, real*, int );
real Dot( real*, real*, int );
real Norm( real*, int );
void Vector_Print( FILE*, char*, real*, int );
void rvec_Copy( rvec, rvec );
void rvec_Scale( rvec, real, rvec );
void rvec_Add( rvec, rvec );
void rvec_ScaledAdd( rvec, real, rvec );
void rvec_Sum( rvec, rvec, rvec );
void rvec_ScaledSum( rvec, real, rvec, real, rvec );
real rvec_Dot( rvec, rvec );
real rvec_ScaledDot( real, rvec, real, rvec );
void rvec_Multiply( rvec, rvec, rvec );
void rvec_iMultiply( rvec, ivec, rvec );
void rvec_Divide( rvec, rvec, rvec );
void rvec_iDivide( rvec, rvec, ivec );
void rvec_Invert( rvec, rvec );
void rvec_Cross( rvec, rvec, rvec );
void rvec_OuterProduct( rtensor, rvec, rvec );
real rvec_Norm_Sqr( rvec );
real rvec_Norm( rvec );
int rvec_isZero( rvec );
void rvec_MakeZero( rvec );
void rvec_Random( rvec );
void rtensor_MakeZero( rtensor );
void rtensor_Multiply( rtensor, rtensor, rtensor );
void rtensor_MatVec( rvec, rtensor, rvec );
void rtensor_Scale( rtensor, real, rtensor );
void rtensor_Add( rtensor, rtensor );
void rtensor_ScaledAdd( rtensor, real, rtensor );
void rtensor_Sum( rtensor, rtensor, rtensor );
void rtensor_ScaledSum( rtensor, real, rtensor, real, rtensor );
void rtensor_Scale( rtensor, real, rtensor );
void rtensor_Copy( rtensor, rtensor );
void rtensor_Identity( rtensor );
void rtensor_Transpose( rtensor, rtensor );
real rtensor_Det( rtensor );
real rtensor_Trace( rtensor );
void Print_rTensor(FILE*,rtensor);
int ivec_isZero( ivec );
int ivec_isEqual( ivec, ivec );
void ivec_MakeZero( ivec );
void ivec_Copy( ivec, ivec );
void ivec_Scale( ivec, real, ivec );
void ivec_rScale( ivec, real, rvec );
void ivec_Sum( ivec, ivec, ivec );
void ivec_ScaledSum( ivec, int, ivec, int, ivec );
void ivec_Add( ivec, ivec );
void ivec_ScaledAdd( ivec, int, ivec );
void ivec_Max( ivec, ivec, ivec );
void ivec_Max3( ivec, ivec, ivec, ivec );
#endif