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; // tally variables real fi_tmp[3], fk_tmp[3], delij[3], delkj[3]; 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 ); } /* tally into per-atom virials */ if (system->pair_ptr->vflag_atom || system->pair_ptr->evflag) { rvec_ScaledSum( delij, 1., system->my_atoms[i].x, -1., system->my_atoms[j].x ); rvec_ScaledSum( delkj, 1., system->my_atoms[k].x, -1., system->my_atoms[j].x ); rvec_Scale(fi_tmp, CEhb2, dcos_theta_di); rvec_Scale(fk_tmp, CEhb2, dcos_theta_dk); rvec_ScaledAdd(fk_tmp, CEhb3/r_jk, dvec_jk); system->pair_ptr->ev_tally3(i,j,k,e_hb,0.0,fi_tmp,fk_tmp,delij,delkj); } #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 }
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; /* tally into per-atom energy */ if( system->evflag) system->pair_ptr->ev_tally(i,j,natoms,1,ebond,0.0,0.0,0.0,0.0,0.0); /* 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)); /* tally into per-atom energy */ if( system->evflag) system->pair_ptr->ev_tally(i,j,natoms,1,estriph,0.0,0.0,0.0,0.0,0.0); 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 } } } } } }