Newer
Older
/*----------------------------------------------------------------------
SerialReax - Reax Force Field Simulator
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
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "two_body_interactions.h"
Kurt A. O'Hearn
committed
#include "bond_orders.h"
#include "list.h"
#include "lookup.h"
#include "vector.h"
void Bond_Energy( reax_system *system, control_params *control,
Kurt A. O'Hearn
committed
simulation_data *data, static_storage *workspace,
Kurt A. O'Hearn
committed
reax_list **lists, output_controls *out_control )
Kurt A. O'Hearn
committed
int i;
Kurt A. O'Hearn
committed
real gp3, gp4, gp7, gp10, gp37, ebond_total;
Kurt A. O'Hearn
committed
reax_list *bonds;
bonds = lists[BONDS];
gp3 = system->reaxprm.gp.l[3];
gp4 = system->reaxprm.gp.l[4];
gp7 = system->reaxprm.gp.l[7];
gp10 = system->reaxprm.gp.l[10];
gp37 = (int) system->reaxprm.gp.l[37];
Kurt A. O'Hearn
committed
ebond_total = 0.0;
Kurt A. O'Hearn
committed
#ifdef _OPENMP
// #pragma omp parallel default(shared) reduction(+: ebond_total)
#endif
Kurt A. O'Hearn
committed
{
Kurt A. O'Hearn
committed
int j, pj;
Kurt A. O'Hearn
committed
int start_i, end_i;
int type_i, type_j;
real ebond, pow_BOs_be2, exp_be12, CEbo;
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;
Kurt A. O'Hearn
committed
#ifdef _OPENMP
// #pragma omp for schedule(guided)
#endif
Kurt A. O'Hearn
committed
for ( i = 0; i < system->N; ++i )
{
start_i = Start_Index(i, bonds);
end_i = End_Index(i, bonds);
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
for ( pj = start_i; pj < end_i; ++pj )
Kurt A. O'Hearn
committed
{
Kurt A. O'Hearn
committed
if ( i < bonds->bond_list[pj].nbr )
Kurt A. O'Hearn
committed
{
/* set the pointers */
Kurt A. O'Hearn
committed
j = bonds->bond_list[pj].nbr;
Kurt A. O'Hearn
committed
type_i = system->atoms[i].type;
type_j = system->atoms[j].type;
Kurt A. O'Hearn
committed
sbp_i = &system->reaxprm.sbp[type_i];
sbp_j = &system->reaxprm.sbp[type_j];
twbp = &system->reaxprm.tbp[type_i][type_j];
bo_ij = &bonds->bond_list[pj].bo_data;
Kurt A. O'Hearn
committed
/* 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 */
ebond = -twbp->De_s * bo_ij->BO_s * exp_be12
- twbp->De_p * bo_ij->BO_pi
- twbp->De_pp * bo_ij->BO_pi2;
ebond_total += ebond;
/* calculate derivatives of Bond Orders */
bo_ij->Cdbo += CEbo;
bo_ij->Cdbopi -= (CEbo + twbp->De_p);
bo_ij->Cdbopi2 -= (CEbo + twbp->De_pp);
Kurt A. O'Hearn
committed
fprintf( out_control->ebond, "%6d%6d%24.15e%24.15e\n",
workspace->orig_id[i], workspace->orig_id[j],
// i+1, j+1,
Kurt A. O'Hearn
committed
bo_ij->BO, ebond );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
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 );
Kurt A. O'Hearn
committed
/* Stabilisation terminal triple bond */
if ( bo_ij->BO >= 1.00 )
Kurt A. O'Hearn
committed
if ( gp37 == 2
|| (sbp_i->mass == 12.0000 && sbp_j->mass == 15.9990)
|| (sbp_j->mass == 12.0000 && sbp_i->mass == 15.9990) )
Kurt A. O'Hearn
committed
{
Kurt A. O'Hearn
committed
//ba = SQR( bo_ij->BO - 2.5 );
exphu = EXP( -gp7 * SQR(bo_ij->BO - 2.5) );
//oboa = abo(j1) - boa;
//obob = abo(j2) - boa;
Kurt A. O'Hearn
committed
exphua1 = EXP(-gp3 * (workspace->total_bond_order[i] - bo_ij->BO));
exphub1 = EXP(-gp3 * (workspace->total_bond_order[j] - bo_ij->BO));
Kurt A. O'Hearn
committed
//ovoab = abo(j1) - aval(it1) + abo(j2) - aval(it2);
Kurt A. O'Hearn
committed
exphuov = EXP(gp4 * (workspace->Delta[i] + workspace->Delta[j]));
hulpov = 1.0 / (1.0 + 25.0 * exphuov);
estriph = gp10 * exphu * hulpov * (exphua1 + exphub1);
Kurt A. O'Hearn
committed
//estrain(j1) = estrain(j1) + 0.5 * estriph;
//estrain(j2) = estrain(j2) + 0.5 * estriph;
Kurt A. O'Hearn
committed
ebond_total += estriph;
decobdbo = gp10 * exphu * hulpov * (exphua1 + exphub1) *
Kurt A. O'Hearn
committed
( gp3 - 2.0 * gp7 * (bo_ij->BO - 2.5) );
Kurt A. O'Hearn
committed
decobdboua = -gp10 * exphu * hulpov *
Kurt A. O'Hearn
committed
(gp3 * exphua1 + 25.0 * gp4 * exphuov * hulpov * (exphua1 + exphub1));
Kurt A. O'Hearn
committed
decobdboub = -gp10 * exphu * hulpov *
Kurt A. O'Hearn
committed
(gp3 * exphub1 + 25.0 * gp4 * exphuov * hulpov * (exphua1 + exphub1));
Kurt A. O'Hearn
committed
bo_ij->Cdbo += decobdbo;
workspace->CdDelta[i] += decobdboua;
workspace->CdDelta[j] += decobdboub;
Kurt A. O'Hearn
committed
fprintf( out_control->ebond,
"%6d%6d%24.15e%24.15e%24.15e%24.15e\n",
workspace->orig_id[i], workspace->orig_id[j],
Kurt A. O'Hearn
committed
//i + 1, j + 1,
Kurt A. O'Hearn
committed
estriph, decobdbo, decobdboua, decobdboub );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
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 );
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
data->E_BE += ebond_total;
void vdW_Coulomb_Energy( reax_system *system, control_params *control,
Kurt A. O'Hearn
committed
simulation_data *data, static_storage *workspace,
Kurt A. O'Hearn
committed
reax_list **lists, output_controls *out_control )
Kurt A. O'Hearn
committed
int i;
Kurt A. O'Hearn
committed
reax_list *far_nbrs;
Kurt A. O'Hearn
committed
real e_vdW_total, e_ele_total;
p_vdW1 = system->reaxprm.gp.l[28];
p_vdW1i = 1.0 / p_vdW1;
far_nbrs = lists[FAR_NBRS];
Kurt A. O'Hearn
committed
e_vdW_total = 0.0;
e_ele_total = 0.0;
Kurt A. O'Hearn
committed
#ifdef _OPENMP
Kurt A. O'Hearn
committed
#pragma omp parallel default(shared) reduction(+: e_vdW_total, e_ele_total)
Kurt A. O'Hearn
committed
#endif
Kurt A. O'Hearn
committed
int j, pj;
Kurt A. O'Hearn
committed
int start_i, end_i;
real self_coef;
real powr_vdW1, powgi_vdW1;
real tmp, r_ij, fn13, exp1, exp2;
real Tap, dTap, dfn13, CEvd, CEclmb;
real dr3gamij_1, dr3gamij_3;
real e_ele, e_vdW, e_core, de_core;
Kurt A. O'Hearn
committed
real d, xcut, bond_softness, d_bond_softness, effpot_diff;
Kurt A. O'Hearn
committed
rvec temp, ext_press;
//rtensor temp_rtensor, total_rtensor;
two_body_parameters *twbp;
far_neighbor_data *nbr_pj;
#ifdef _OPENMP
int tid;
tid = omp_get_thread_num( );
#endif
Kurt A. O'Hearn
committed
e_ele = 0.0;
e_vdW = 0.0;
e_core = 0.0;
de_core = 0.0;
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
#ifdef _OPENMP
Kurt A. O'Hearn
committed
#pragma omp for schedule(guided)
Kurt A. O'Hearn
committed
#endif
Kurt A. O'Hearn
committed
for ( i = 0; i < system->N; ++i )
{
start_i = Start_Index( i, far_nbrs );
end_i = End_Index( i, far_nbrs );
for ( pj = start_i; pj < end_i; ++pj )
Kurt A. O'Hearn
committed
if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_cut )
Kurt A. O'Hearn
committed
nbr_pj = &far_nbrs->far_nbr_list[pj];
Kurt A. O'Hearn
committed
j = nbr_pj->nbr;
r_ij = nbr_pj->d;
twbp = &system->reaxprm.tbp[ system->atoms[i].type ]
[ system->atoms[j].type ];
Kurt A. O'Hearn
committed
self_coef = (i == j) ? 0.5 : 1.0; // for supporting small boxes!
/* 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;
Kurt A. O'Hearn
committed
/* vdWaals Calculations */
if ( system->reaxprm.gp.vdw_type == 1 || system->reaxprm.gp.vdw_type == 3 )
{
/* shielding */
powr_vdW1 = POW( r_ij, p_vdW1 );
powgi_vdW1 = POW( 1.0 / twbp->gamma_w, p_vdW1 );
Kurt A. O'Hearn
committed
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) );
Kurt A. O'Hearn
committed
e_vdW = self_coef * Tap * twbp->D * (exp1 - 2.0 * exp2);
e_vdW_total += e_vdW;
Kurt A. O'Hearn
committed
dfn13 = POW( powr_vdW1 + powgi_vdW1, p_vdW1i - 1.0) *
POW( r_ij, p_vdW1 - 2.0 );
Kurt A. O'Hearn
committed
CEvd = self_coef * ( dTap * twbp->D * (exp1 - 2 * exp2) -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) *
(exp1 - exp2) * dfn13 );
}
/* no shielding */
else
{
exp1 = EXP( twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
exp2 = EXP( 0.5 * twbp->alpha * (1.0 - r_ij / twbp->r_vdW) );
Kurt A. O'Hearn
committed
e_vdW = self_coef * Tap * twbp->D * (exp1 - 2.0 * exp2);
e_vdW_total += e_vdW;
Kurt A. O'Hearn
committed
CEvd = self_coef * ( dTap * twbp->D * (exp1 - 2.0 * exp2) -
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) *
(exp1 - exp2) );
}
Kurt A. O'Hearn
committed
if ( system->reaxprm.gp.vdw_type == 2 || system->reaxprm.gp.vdw_type == 3 )
{
/* innner wall */
Kurt A. O'Hearn
committed
e_core = twbp->ecore * EXP( twbp->acore * (1.0 - (r_ij / twbp->rcore)) );
Kurt A. O'Hearn
committed
e_vdW += self_coef * Tap * e_core;
e_vdW_total += self_coef * Tap * e_core;
Kurt A. O'Hearn
committed
de_core = -(twbp->acore / twbp->rcore) * e_core;
CEvd += self_coef * ( dTap * e_core + Tap * de_core );
}
Kurt A. O'Hearn
committed
/* Coulomb Calculations */
dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
dr3gamij_3 = POW( dr3gamij_1 , 1.0 / 3.0 );
Kurt A. O'Hearn
committed
tmp = Tap / dr3gamij_3;
Kurt A. O'Hearn
committed
e_ele = self_coef * C_ELE * system->atoms[i].q * system->atoms[j].q * tmp;
Kurt A. O'Hearn
committed
e_ele_total += e_ele;
Kurt A. O'Hearn
committed
CEclmb = self_coef * C_ELE * system->atoms[i].q * system->atoms[j].q *
Kurt A. O'Hearn
committed
( dTap - Tap * r_ij / dr3gamij_1 ) / dr3gamij_3;
if ( control->ensemble == NVE || control->ensemble == nhNVT
|| control->ensemble == bNVT )
Kurt A. O'Hearn
committed
{
#ifndef _OPENMP
rvec_ScaledAdd( system->atoms[i].f,
-(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( system->atoms[j].f,
+(CEvd + CEclmb), nbr_pj->dvec );
#else
rvec_ScaledAdd( workspace->f_local[tid * system->N + i],
-(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_local[tid * system->N + j],
+(CEvd + CEclmb), nbr_pj->dvec );
#endif
}
Kurt A. O'Hearn
committed
/* aNPT, iNPT or sNPT */
Kurt A. O'Hearn
committed
else
{
/* 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 );
#ifndef _OPENMP
rvec_ScaledAdd( system->atoms[i].f, -1., temp );
rvec_Add( system->atoms[j].f, temp );
#else
rvec_ScaledAdd( workspace->f_local[tid * system->N + i], -1., temp );
rvec_Add( workspace->f_local[tid * system->N + j], temp );
#endif
Kurt A. O'Hearn
committed
rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
Kurt A. O'Hearn
committed
#ifdef _OPENMP
#pragma omp critical (vdW_Coulomb_Energy_ext_press)
#endif
Kurt A. O'Hearn
committed
{
rvec_Add( data->ext_press, ext_press );
}
Kurt A. O'Hearn
committed
#if defined(DEBUG_FOCUS)
fprintf( stderr, "nonbonded(%d,%d): rel_box (%f %f %f)",
i, j, nbr_pj->rel_box[0],
nbr_pj->rel_box[1], nbr_pj->rel_box[2] );
fprintf( stderr, "force(%f %f %f)", temp[0], temp[1], temp[2] );
fprintf( stderr, "ext_press (%12.6f %12.6f %12.6f)\n",
data->ext_press[0], data->ext_press[1],
data->ext_press[2] );
#endif
// /* This part is intended for a fully-flexible box */
// rvec_OuterProduct( temp_rtensor, nbr_pj->dvec, system->atoms[i].x );
// rtensor_Scale( total_rtensor, F_C * -(CEvd + CEclmb), temp_rtensor );
// rvec_OuterProduct( temp_rtensor, nbr_pj->dvec, system->atoms[j].x );
// rtensor_ScaledAdd( total_rtensor, F_C * +(CEvd + CEclmb), temp_rtensor );
//
// /* This is an external force due to an imaginary nbr */
// if ( nbr_pj->imaginary )
// rtensor_ScaledAdd( data->flex_bar.P, -1.0, total_rtensor );
// /* This interaction is completely internal */
// else
// rtensor_Add( data->flex_bar.P, total_rtensor );
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
rvec_MakeZero( temp );
rvec_ScaledAdd( temp, +CEvd, nbr_pj->dvec );
fprintf( out_control->evdw,
"%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
//i+1, j+1,
MIN( workspace->orig_id[i], workspace->orig_id[j] ),
MAX( workspace->orig_id[i], workspace->orig_id[j] ),
r_ij, e_vdW, temp[0], temp[1], temp[2]/*, e_vdW_total*/ );
fprintf( out_control->ecou, "%6d%6d%24.15e%24.15e%24.15e%24.15e\n",
MIN( workspace->orig_id[i], workspace->orig_id[j] ),
MAX( workspace->orig_id[i], workspace->orig_id[j] ),
r_ij, system->atoms[i].q, system->atoms[j].q,
e_ele/*, e_ele_total*/ );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
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 );
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
//TODO: better integration of ACKS2 code below with above code for performance
#ifdef _OPENMP
#pragma omp barrier
#endif
/* contribution to energy and gradients (atoms and cell)
* due to geometry-dependent terms in the ACKS2
* kinetic energy */
if ( control->charge_method == ACKS2_CM )
{
Kurt A. O'Hearn
committed
#ifdef _OPENMP
#pragma omp for schedule(guided)
#endif
Kurt A. O'Hearn
committed
for ( i = 0; i < system->N; ++i )
{
for ( pj = Start_Index(i, far_nbrs); pj < End_Index(i, far_nbrs); ++pj )
{
Kurt A. O'Hearn
committed
nbr_pj = &far_nbrs->far_nbr_list[pj];
j = nbr_pj->nbr;
/* kinetic energy terms */
xcut = 0.5 * ( system->reaxprm.sbp[ system->atoms[i].type ].b_s_acks2
+ system->reaxprm.sbp[ system->atoms[j].type ].b_s_acks2 );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
if ( far_nbrs->far_nbr_list[pj].d < xcut )
{
d = far_nbrs->far_nbr_list[pj].d / xcut;
bond_softness = system->reaxprm.gp.l[34] * POW( d, 3.0 )
* POW( 1.0 - d, 6.0 );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
if ( bond_softness > 0.0 )
Kurt A. O'Hearn
committed
{
Kurt A. O'Hearn
committed
/* Coulombic energy contribution */
effpot_diff = workspace->s[0][system->N + i]
- workspace->s[0][system->N + j];
e_ele = -0.5 * KCALpMOL_to_EV * bond_softness
* SQR( effpot_diff );
e_ele_total += e_ele;
/* forces contribution */
d_bond_softness = system->reaxprm.gp.l[34]
* 3.0 / xcut * POW( d, 2.0 )
* POW( 1.0 - d, 5.0 ) * (1.0 - 3.0 * d);
d_bond_softness = -0.5 * d_bond_softness
* SQR( effpot_diff );
d_bond_softness = KCALpMOL_to_EV * d_bond_softness
/ far_nbrs->far_nbr_list[pj].d;
#if defined(DEBUG_FOCUS)
fprintf( stderr, "%6d%6d%12.5f%12.5f%12.5f\n",
j + 1, i + 1,
d_bond_softness * nbr_pj->dvec[0],
d_bond_softness * nbr_pj->dvec[1],
d_bond_softness * nbr_pj->dvec[2] ); fflush( stderr );
#endif
Kurt A. O'Hearn
committed
#ifndef _OPENMP
Kurt A. O'Hearn
committed
rvec_ScaledAdd( system->atoms[i].f,
-d_bond_softness, nbr_pj->dvec );
rvec_ScaledAdd( system->atoms[j].f,
d_bond_softness, nbr_pj->dvec );
Kurt A. O'Hearn
committed
#else
Kurt A. O'Hearn
committed
rvec_ScaledAdd( workspace->f_local[tid * system->N + i],
-d_bond_softness, nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_local[tid * system->N + j],
d_bond_softness, nbr_pj->dvec );
Kurt A. O'Hearn
committed
#endif
}
}
}
}
}
Kurt A. O'Hearn
committed
data->E_vdW = e_vdW_total;
data->E_Ele = e_ele_total;
Kurt A. O'Hearn
committed
#if defined(DEBUG)
fprintf( stderr, "nonbonded: ext_press (%24.15e %24.15e %24.15e)\n",
data->ext_press[0], data->ext_press[1], data->ext_press[2] );
#endif
void LR_vdW_Coulomb( reax_system *system, control_params *control,
static_storage *workspace, int i, int j, real r_ij, LR_data *lr )
real p_vdW1 = system->reaxprm.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->reaxprm.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;
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) );
/* fprintf(stderr,"vdW: Tap:%f, r: %f, f13:%f, D:%f, Energy:%f,\
Gamma_w:%f, p_vdw: %f, alpha: %f, r_vdw: %f, %lf %lf\n",
Tap, r_ij, fn13, twbp->D, Tap * twbp->D * (exp1 - 2.0 * exp2),
powgi_vdW1, p_vdW1, twbp->alpha, twbp->r_vdW, exp1, exp2); */
dfn13 = POW( powr_vdW1 + powgi_vdW1, p_vdW1i - 1.0 )
* POW( r_ij, p_vdW1 - 2.0 );
Kurt A. O'Hearn
committed
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
Kurt A. O'Hearn
committed
/* vdWaals Calculations */
if ( system->reaxprm.gp.vdw_type == 1 || system->reaxprm.gp.vdw_type == 3 )
Kurt A. O'Hearn
committed
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) *
Kurt A. O'Hearn
committed
POW( r_ij, p_vdW1 - 2.0 );
Kurt A. O'Hearn
committed
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2) * dfn13;
Kurt A. O'Hearn
committed
/* no shielding */
else
{
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) -
Kurt A. O'Hearn
committed
Tap * twbp->D * (twbp->alpha / twbp->r_vdW) * (exp1 - exp2);
Kurt A. O'Hearn
committed
if ( system->reaxprm.gp.vdw_type == 2 || system->reaxprm.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 );
Kurt A. O'Hearn
committed
dr3gamij_3 = POW( dr3gamij_1 , 1.0 / 3.0 );
tmp = Tap / dr3gamij_3;
lr->H = EV_to_KCALpMOL * tmp;
Kurt A. O'Hearn
committed
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->atoms[i].type, j, system->atoms[j].type,
twbp->gamma, Tap, dr3gamij_3,
system->atoms[i].q, system->atoms[j].q ); */
Kurt A. O'Hearn
committed
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->atoms[i].q, system->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 ); */
}
void Tabulated_vdW_Coulomb_Energy( reax_system *system, control_params *control,
Kurt A. O'Hearn
committed
simulation_data *data, static_storage *workspace, reax_list **lists,
Kurt A. O'Hearn
committed
output_controls *out_control )
Kurt A. O'Hearn
committed
int steps, update_freq, update_energies;
Kurt A. O'Hearn
committed
reax_list *far_nbrs;
Kurt A. O'Hearn
committed
real e_vdW_total, e_ele_total;
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;
Kurt A. O'Hearn
committed
e_vdW_total = 0.0;
e_ele_total = 0.0;
Kurt A. O'Hearn
committed
#ifdef _OPENMP
Kurt A. O'Hearn
committed
#pragma omp parallel default(shared) reduction(+: e_vdW_total, e_ele_total)
Kurt A. O'Hearn
committed
#endif
Kurt A. O'Hearn
committed
int i, j, pj, r;
int type_i, type_j, tmin, tmax;
int start_i, end_i;
real r_ij, self_coef, base, dif;
real e_vdW, e_ele;
real CEvd, CEclmb;
rvec temp, ext_press;
far_neighbor_data *nbr_pj;
LR_lookup_table *t;
#ifdef _OPENMP
int tid;
tid = omp_get_thread_num( );
Kurt A. O'Hearn
committed
#pragma omp for schedule(guided)
Kurt A. O'Hearn
committed
#endif
Kurt A. O'Hearn
committed
for ( i = 0; i < system->N; ++i )
{
type_i = system->atoms[i].type;
start_i = Start_Index(i, far_nbrs);
end_i = End_Index(i, far_nbrs);
for ( pj = start_i; pj < end_i; ++pj )
Kurt A. O'Hearn
committed
if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_cut )
Kurt A. O'Hearn
committed
nbr_pj = &far_nbrs->far_nbr_list[pj];
Kurt A. O'Hearn
committed
j = nbr_pj->nbr;
type_j = system->atoms[j].type;
r_ij = nbr_pj->d;
self_coef = (i == j) ? 0.5 : 1.0;
tmin = MIN( type_i, type_j );
tmax = MAX( type_i, type_j );
Kurt A. O'Hearn
committed
t = &workspace->LR[tmin][tmax];
Kurt A. O'Hearn
committed
/* Cubic Spline Interpolation */
Kurt A. O'Hearn
committed
r = (int) (r_ij * t->inv_dx);
Kurt A. O'Hearn
committed
if ( r == 0 )
{
++r;
}
Kurt A. O'Hearn
committed
base = (real) (r + 1) * t->dx;
Kurt A. O'Hearn
committed
dif = r_ij - base;
Kurt A. O'Hearn
committed
#if defined(DEBUG)
fprintf( stderr, "r: %f, i: %d, base: %f, dif: %f\n", r, i, base, dif );
#endif
Kurt A. O'Hearn
committed
if ( update_energies )
{
Kurt A. O'Hearn
committed
e_vdW = ((t->vdW[r].d * dif + t->vdW[r].c) * dif + t->vdW[r].b)
* dif + t->vdW[r].a;
Kurt A. O'Hearn
committed
e_vdW *= self_coef;
Kurt A. O'Hearn
committed
e_ele = ((t->ele[r].d * dif + t->ele[r].c) * dif + t->ele[r].b)
* dif + t->ele[r].a;
Kurt A. O'Hearn
committed
e_ele *= self_coef * system->atoms[i].q * system->atoms[j].q;
Kurt A. O'Hearn
committed
e_vdW_total += e_vdW;
e_ele_total += e_ele;
}
Kurt A. O'Hearn
committed
CEvd = ((t->CEvd[r].d * dif + t->CEvd[r].c) * dif + t->CEvd[r].b)
* dif + t->CEvd[r].a;
Kurt A. O'Hearn
committed
CEvd *= self_coef;
Kurt A. O'Hearn
committed
// CEvd = (3 * t->vdW[r].d * dif + 2 * t->vdW[r].c) * dif + t->vdW[r].b;
Kurt A. O'Hearn
committed
CEclmb = ((t->CEclmb[r].d * dif + t->CEclmb[r].c) * dif + t->CEclmb[r].b)
* dif + t->CEclmb[r].a;
Kurt A. O'Hearn
committed
CEclmb *= self_coef * system->atoms[i].q * system->atoms[j].q;
if ( control->ensemble == NVE || control->ensemble == nhNVT
|| control->ensemble == bNVT )
Kurt A. O'Hearn
committed
{
#ifndef _OPENMP
rvec_ScaledAdd( system->atoms[i].f, -(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( system->atoms[j].f, +(CEvd + CEclmb), nbr_pj->dvec );
#else
rvec_ScaledAdd( workspace->f_local[tid * system->N + i],
-(CEvd + CEclmb), nbr_pj->dvec );
rvec_ScaledAdd( workspace->f_local[tid * system->N + j],
+(CEvd + CEclmb), nbr_pj->dvec );
#endif
}
Kurt A. O'Hearn
committed
/* aNPT, iNPT or sNPT */
else
Kurt A. O'Hearn
committed
{
/* 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 );
#ifndef _OPENMP
rvec_ScaledAdd( system->atoms[i].f, -1., temp );
rvec_Add( system->atoms[j].f, temp );
#else
rvec_ScaledAdd( workspace->f_local[tid * system->N + i], -1., temp );
rvec_Add( workspace->f_local[tid * system->N + j], temp );
#endif
rvec_iMultiply( ext_press, nbr_pj->rel_box, temp );
Kurt A. O'Hearn
committed
#ifdef _OPENMP
#pragma omp critical (Tabulated_vdW_Coulomb_Energy_ext_press)
#endif
Kurt A. O'Hearn
committed
{
rvec_Add( data->ext_press, ext_press );
}
}
Kurt A. O'Hearn
committed
fprintf( out_control->evdw, "%6d%6d%24.15e%24.15e%24.15e\n",
workspace->orig_id[i], workspace->orig_id[j],
r_ij, e_vdW, data->E_vdW );
fprintf( out_control->ecou, "%6d%6d%24.15e%24.15e%24.15e%24.15e%24.15e\n",
workspace->orig_id[i], workspace->orig_id[j],
r_ij, system->atoms[i].q, system->atoms[j].q,
e_ele, data->E_Ele );
Kurt A. O'Hearn
committed
Kurt A. O'Hearn
committed
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 );
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
}
Kurt A. O'Hearn
committed
data->E_vdW += e_vdW_total;
data->E_Ele += e_ele_total;