forked from lijiext/lammps
git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@5143 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
parent
c2723c7d27
commit
bfd6a79fe6
|
@ -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
|
|
@ -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/>.
|
|
@ -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];
|
||||
}
|
|
@ -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
|
|
@ -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++];
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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" );
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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 ); */
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
*/
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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] );
|
||||
}
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue