Example #1
0
void Init_Forces_Tab(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists,
		output_controls *out_control) {
	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 tmin, tmax, r;
	int ihb, jhb, ihb_top, jhb_top;
	int flag;
	real r_ij, r2, self_coef;
	real val, dif, base;
	real C12, C34, C56;
	real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
	real BO, BO_s, BO_pi, BO_pi2;
	real p_boc1, p_boc2;
	sparse_matrix *H;
	list *far_nbrs, *bonds, *hbonds;
	single_body_parameters *sbp_i, *sbp_j;
	two_body_parameters *twbp;
	far_neighbor_data *nbr_pj;
	LR_lookup_table *t;
	reax_atom *atom_i, *atom_j;
	bond_data *ibond, *jbond;
	bond_order_data *bo_ij, *bo_ji;

	far_nbrs = *lists + FAR_NBRS;
	bonds = *lists + BONDS;
	hbonds = *lists + HBONDS;

	H = workspace->H;
	Htop = 0;
	num_bonds = 0;
	num_hbonds = 0;
	btop_i = btop_j = 0;
	p_boc1 = system->reaxprm.gp.l[0];
	p_boc2 = system->reaxprm.gp.l[1];

	for (i = 0; i < system->N; ++i) {
		atom_i = &(system->atoms[i]);
		type_i = atom_i->type;
		start_i = Start_Index(i, far_nbrs);
		end_i = End_Index(i, far_nbrs);
		H->start[i] = Htop;
		btop_i = End_Index(i, bonds);
		sbp_i = &(system->reaxprm.sbp[type_i]);
		ihb = ihb_top = -1;
		if (control->hb_cut > 0 && (ihb = sbp_i->p_hbond) == 1)
			ihb_top = End_Index(workspace->hbond_index[i], hbonds);

		for (pj = start_i; pj < end_i; ++pj) {
			nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
			j = nbr_pj->nbr;
			atom_j = &(system->atoms[j]);

			flag = 0;
			if ((data->step - data->prev_steps) % control->reneighbor == 0) {
				if (nbr_pj->d <= control->r_cut)
					flag = 1;
				else
					flag = 0;
			} else if ((nbr_pj->d = Sq_Distance_on_T3(atom_i->x, atom_j->x,
					&(system->box), nbr_pj->dvec)) <= SQR(control->r_cut)) {
				nbr_pj->d = sqrt(nbr_pj->d);
				flag = 1;
			}

			if (flag) {
				type_j = system->atoms[j].type;
				r_ij = nbr_pj->d;
				sbp_j = &(system->reaxprm.sbp[type_j]);
				twbp = &(system->reaxprm.tbp[type_i][type_j]);
				self_coef = (i == j) ? 0.5 : 1.0;
				tmin = MIN( type_i, type_j );
				tmax = MAX( type_i, type_j );
				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;

				H->entries[Htop].j = j;
				H->entries[Htop].val = self_coef * val;
				++Htop;

				/* hydrogen bond lists */
				if (control->hb_cut > 0 && (ihb == 1 || ihb == 2) && nbr_pj->d
						<= control->hb_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 (ihb == 2 && jhb == 1) {
						jhb_top = End_Index(workspace->hbond_index[j], 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(workspace->hbond_index[j], jhb_top + 1,
								hbonds);
						++num_hbonds;
					}
				}

				/* uncorrected bond orders */
				if (far_nbrs->select.far_nbr_list[pj].d <= control->nbr_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) {
						num_bonds += 2;
						/****** bonds i-j and j-i ******/
						ibond = &(bonds->select.bond_list[btop_i]);
						btop_j = End_Index(j, bonds);
						jbond = &(bonds->select.bond_list[btop_j]);

						ibond->nbr = j;
						jbond->nbr = i;
						ibond->d = r_ij;
						jbond->d = r_ij;
						rvec_Copy(ibond->dvec, nbr_pj->dvec);
						rvec_Scale(jbond->dvec, -1, nbr_pj->dvec);
						ivec_Copy(ibond->rel_box, nbr_pj->rel_box);
						ivec_Scale(jbond->rel_box, -1, nbr_pj->rel_box);
						ibond->dbond_index = btop_i;
						jbond->dbond_index = btop_i;
						ibond->sym_index = btop_j;
						jbond->sym_index = btop_i;
						++btop_i;
						Set_End_Index(j, btop_j + 1, bonds);

						bo_ij = &(ibond->bo_data);
						bo_ji = &(jbond->bo_data);
						bo_ji->BO = bo_ij->BO = BO;
						bo_ji->BO_s = bo_ij->BO_s = BO_s;
						bo_ji->BO_pi = bo_ij->BO_pi = BO_pi;
						bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2;

						/* Bond Order page2-3, derivative of total bond order prime */
						Cln_BOp_s = twbp->p_bo2 * C12 / r2;
						Cln_BOp_pi = twbp->p_bo4 * C34 / r2;
						Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2;

						/* Only dln_BOp_xx wrt. dr_i is stored here, note that
						 dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s,
								ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi, -bo_ij->BO_pi
								* Cln_BOp_pi, ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi2, -bo_ij->BO_pi2
								* Cln_BOp_pi2, ibond->dvec);
						rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s);
						rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi);
						rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2);

						/* Only dBOp wrt. dr_i is stored here, note that
						 dBOp/dr_i = -dBOp/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s
								+ bo_ij->BO_pi * Cln_BOp_pi + bo_ij->BO_pi2
								* Cln_BOp_pi2), ibond->dvec);
						rvec_Scale(bo_ji->dBOp, -1., bo_ij->dBOp);

						rvec_Add(workspace->dDeltap_self[i], bo_ij->dBOp);
						rvec_Add(workspace->dDeltap_self[j], bo_ji->dBOp);

						bo_ij->BO_s -= control->bo_cut;
						bo_ij->BO -= control->bo_cut;
						bo_ji->BO_s -= control->bo_cut;
						bo_ji->BO -= control->bo_cut;
						workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp
						workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp
						bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0;
						bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0;

						Set_End_Index(j, btop_j + 1, bonds);
					}
				}
			}
		}

		H->entries[Htop].j = i;
		H->entries[Htop].val = system->reaxprm.sbp[type_i].eta;
		++Htop;

		Set_End_Index(i, btop_i, bonds);
		if (ihb == 1)
			Set_End_Index(workspace->hbond_index[i], ihb_top, hbonds);
	}

	// mark the end of j list
	H->start[i] = Htop;
	/* validate lists - decide if reallocation is required! */
	Validate_Lists(workspace, lists, data->step, system->N, H->m, Htop,
			num_bonds, num_hbonds);

#if defined(DEBUG_FOCUS)
	fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n",
			data->step, Htop, num_bonds, num_hbonds );
	//Print_Bonds( system, bonds, "sbonds.out" );
	//Print_Bond_List2( system, bonds, "sbonds.out" );
	//Print_Sparse_Matrix2( H, "H.out" );
#endif
}
Example #2
0
void Init_Forces(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists,
		output_controls *out_control) {
	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 flag;
	real r_ij, r2, self_coef;
	real dr3gamij_1, dr3gamij_3, Tap;
	//real val, dif, base;
	real C12, C34, C56;
	real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
	real BO, BO_s, BO_pi, BO_pi2;
	real p_boc1, p_boc2;
	sparse_matrix *H;
	list *far_nbrs, *bonds, *hbonds;
	single_body_parameters *sbp_i, *sbp_j;
	two_body_parameters *twbp;
	far_neighbor_data *nbr_pj;
	//LR_lookup_table *t;
	reax_atom *atom_i, *atom_j;
	bond_data *ibond, *jbond;
	bond_order_data *bo_ij, *bo_ji;

	far_nbrs = *lists + FAR_NBRS;
	bonds = *lists + BONDS;
	hbonds = *lists + HBONDS;

	H = workspace->H;
	Htop = 0;
	num_bonds = 0;
	num_hbonds = 0;
	btop_i = btop_j = 0;
	p_boc1 = system->reaxprm.gp.l[0];
	p_boc2 = system->reaxprm.gp.l[1];

	for (i = 0; i < system->N; ++i) {
		atom_i = &(system->atoms[i]);
		type_i = atom_i->type;
		start_i = Start_Index(i, far_nbrs);
		end_i = End_Index(i, far_nbrs);
		H->start[i] = Htop;
		btop_i = End_Index(i, bonds);
		sbp_i = &(system->reaxprm.sbp[type_i]);
		ihb = ihb_top = -1;
		if (control->hb_cut > 0 && (ihb = sbp_i->p_hbond) == 1)
			ihb_top = End_Index(workspace->hbond_index[i], hbonds);

		for (pj = start_i; pj < end_i; ++pj) {
			nbr_pj = &(far_nbrs->select.far_nbr_list[pj]);
			j = nbr_pj->nbr;
			atom_j = &(system->atoms[j]);

			flag = 0;
			if ((data->step - data->prev_steps) % control->reneighbor == 0) {
				if (nbr_pj->d <= control->r_cut)
					flag = 1;
				else
					flag = 0;
			} else if ((nbr_pj->d = Sq_Distance_on_T3(atom_i->x, atom_j->x,
					&(system->box), nbr_pj->dvec)) <= SQR(control->r_cut)) {
				nbr_pj->d = sqrt(nbr_pj->d);
				flag = 1;
			}

			if (flag) {
				type_j = system->atoms[j].type;
				r_ij = nbr_pj->d;
				sbp_j = &(system->reaxprm.sbp[type_j]);
				twbp = &(system->reaxprm.tbp[type_i][type_j]);
				self_coef = (i == j) ? 0.5 : 1.0;

				/* H matrix entry */
				Tap = control->Tap7 * r_ij + control->Tap6;
				Tap = Tap * r_ij + control->Tap5;
				Tap = Tap * r_ij + control->Tap4;
				Tap = Tap * r_ij + control->Tap3;
				Tap = Tap * r_ij + control->Tap2;
				Tap = Tap * r_ij + control->Tap1;
				Tap = Tap * r_ij + control->Tap0;

				dr3gamij_1 = (r_ij * r_ij * r_ij + twbp->gamma);
				dr3gamij_3 = POW(dr3gamij_1, 0.33333333333333);

				H->entries[Htop].j = j;
				H->entries[Htop].val = self_coef * Tap * EV_to_KCALpMOL
						/ dr3gamij_3;
				++Htop;

				/* hydrogen bond lists */
				if (control->hb_cut > 0 && (ihb == 1 || ihb == 2) && nbr_pj->d
						<= control->hb_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 (ihb == 2 && jhb == 1) {
						jhb_top = End_Index(workspace->hbond_index[j], 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(workspace->hbond_index[j], jhb_top + 1,
								hbonds);
						++num_hbonds;
					}
				}

				/* uncorrected bond orders */
				if (far_nbrs->select.far_nbr_list[pj].d <= control->nbr_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) {
						num_bonds += 2;
						/****** bonds i-j and j-i ******/
						ibond = &(bonds->select.bond_list[btop_i]);
						btop_j = End_Index(j, bonds);
						jbond = &(bonds->select.bond_list[btop_j]);

						ibond->nbr = j;
						jbond->nbr = i;
						ibond->d = r_ij;
						jbond->d = r_ij;
						rvec_Copy(ibond->dvec, nbr_pj->dvec);
						rvec_Scale(jbond->dvec, -1, nbr_pj->dvec);
						ivec_Copy(ibond->rel_box, nbr_pj->rel_box);
						ivec_Scale(jbond->rel_box, -1, nbr_pj->rel_box);
						ibond->dbond_index = btop_i;
						jbond->dbond_index = btop_i;
						ibond->sym_index = btop_j;
						jbond->sym_index = btop_i;
						++btop_i;
						Set_End_Index(j, btop_j + 1, bonds);

						bo_ij = &(ibond->bo_data);
						bo_ji = &(jbond->bo_data);
						bo_ji->BO = bo_ij->BO = BO;
						bo_ji->BO_s = bo_ij->BO_s = BO_s;
						bo_ji->BO_pi = bo_ij->BO_pi = BO_pi;
						bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2;

						/* Bond Order page2-3, derivative of total bond order prime */
						Cln_BOp_s = twbp->p_bo2 * C12 / r2;
						Cln_BOp_pi = twbp->p_bo4 * C34 / r2;
						Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2;

						/* Only dln_BOp_xx wrt. dr_i is stored here, note that
						 dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s,
								ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi, -bo_ij->BO_pi
								* Cln_BOp_pi, ibond->dvec);
						rvec_Scale(bo_ij->dln_BOp_pi2, -bo_ij->BO_pi2
								* Cln_BOp_pi2, ibond->dvec);
						rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s);
						rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi);
						rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2);

						/* Only dBOp wrt. dr_i is stored here, note that
						 dBOp/dr_i = -dBOp/dr_j and all others are 0 */
						rvec_Scale(bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s
								+ bo_ij->BO_pi * Cln_BOp_pi + bo_ij->BO_pi2
								* Cln_BOp_pi2), ibond->dvec);
						rvec_Scale(bo_ji->dBOp, -1., bo_ij->dBOp);

						rvec_Add(workspace->dDeltap_self[i], bo_ij->dBOp);
						rvec_Add(workspace->dDeltap_self[j], bo_ji->dBOp);

						bo_ij->BO_s -= control->bo_cut;
						bo_ij->BO -= control->bo_cut;
						bo_ji->BO_s -= control->bo_cut;
						bo_ji->BO -= control->bo_cut;
						workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp
						workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp
						bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0;
						bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0;

						/*fprintf( stderr, "%d %d %g %g %g\n",
						 i+1, j+1, bo_ij->BO, bo_ij->BO_pi, bo_ij->BO_pi2 );*/

						/*fprintf( stderr, "Cln_BOp_s: %f, pbo2: %f, C12:%f\n",
						 Cln_BOp_s, twbp->p_bo2, C12 );
						 fprintf( stderr, "Cln_BOp_pi: %f, pbo4: %f, C34:%f\n",
						 Cln_BOp_pi, twbp->p_bo4, C34 );
						 fprintf( stderr, "Cln_BOp_pi2: %f, pbo6: %f, C56:%f\n",
						 Cln_BOp_pi2, twbp->p_bo6, C56 );*/
						/*fprintf(stderr, "pbo1: %f, pbo2:%f\n", twbp->p_bo1, twbp->p_bo2);
						 fprintf(stderr, "pbo3: %f, pbo4:%f\n", twbp->p_bo3, twbp->p_bo4);
						 fprintf(stderr, "pbo5: %f, pbo6:%f\n", twbp->p_bo5, twbp->p_bo6);
						 fprintf( stderr, "r_s: %f, r_p: %f, r_pp: %f\n",
						 twbp->r_s, twbp->r_p, twbp->r_pp );
						 fprintf( stderr, "C12: %g, C34:%g, C56:%g\n", C12, C34, C56 );*/

						/*fprintf( stderr, "\tfactors: %g %g %g\n",
						 -(bo_ij->BO_s * Cln_BOp_s + bo_ij->BO_pi * Cln_BOp_pi +
						 bo_ij->BO_pi2 * Cln_BOp_pp),
						 -bo_ij->BO_pi * Cln_BOp_pi, -bo_ij->BO_pi2 * Cln_BOp_pi2 );*/
						/*fprintf( stderr, "dBOpi:\t[%g, %g, %g]\n",
						 bo_ij->dBOp[0], bo_ij->dBOp[1], bo_ij->dBOp[2] );
						 fprintf( stderr, "dBOpi:\t[%g, %g, %g]\n",
						 bo_ij->dln_BOp_pi[0], bo_ij->dln_BOp_pi[1],
						 bo_ij->dln_BOp_pi[2] );
						 fprintf( stderr, "dBOpi2:\t[%g, %g, %g]\n\n",
						 bo_ij->dln_BOp_pi2[0], bo_ij->dln_BOp_pi2[1],
						 bo_ij->dln_BOp_pi2[2] );*/

						Set_End_Index(j, btop_j + 1, bonds);
					}
				}
			}
		}

		H->entries[Htop].j = i;
		H->entries[Htop].val = system->reaxprm.sbp[type_i].eta;
		++Htop;

		Set_End_Index(i, btop_i, bonds);
		if (ihb == 1)
			Set_End_Index(workspace->hbond_index[i], ihb_top, hbonds);
		//fprintf( stderr, "%d bonds start: %d, end: %d\n",
		//     i, Start_Index( i, bonds ), End_Index( i, bonds ) );
	}

	// mark the end of j list
	H->start[i] = Htop;
	/* validate lists - decide if reallocation is required! */
	Validate_Lists(workspace, lists, data->step, system->N, H->m, Htop,
			num_bonds, num_hbonds);

#if defined(DEBUG_FOCUS)
	fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n",
			data->step, Htop, num_bonds, num_hbonds );

#endif
}
Example #3
0
int BOp( storage *workspace, reax_list *bonds, double bo_cut,
         int i, int btop_i, far_neighbor_data *nbr_pj,
         single_body_parameters *sbp_i, single_body_parameters *sbp_j,
         two_body_parameters *twbp ) {
  int j, btop_j;
  double r2, C12, C34, C56;
  double Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
  double BO, BO_s, BO_pi, BO_pi2;
  bond_data *ibond, *jbond;
  bond_order_data *bo_ij, *bo_ji;

  j = nbr_pj->nbr;
  r2 = SQR(nbr_pj->d);

  if( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0 ) {
    C12 = twbp->p_bo1 * pow( nbr_pj->d / twbp->r_s, twbp->p_bo2 );
    BO_s = (1.0 + 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( nbr_pj->d / 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( nbr_pj->d / 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 >= bo_cut ) {
    /****** bonds i-j and j-i ******/
    ibond = &( bonds->select.bond_list[btop_i] );
    btop_j = End_Index( j, bonds );
    jbond = &(bonds->select.bond_list[btop_j]);

    ibond->nbr = j;
    jbond->nbr = i;
    ibond->d = nbr_pj->d;
    jbond->d = nbr_pj->d;
    rvec_Copy( ibond->dvec, nbr_pj->dvec );
    rvec_Scale( jbond->dvec, -1, nbr_pj->dvec );
    ivec_Copy( ibond->rel_box, nbr_pj->rel_box );
    ivec_Scale( jbond->rel_box, -1, nbr_pj->rel_box );
    ibond->dbond_index = btop_i;
    jbond->dbond_index = btop_i;
    ibond->sym_index = btop_j;
    jbond->sym_index = btop_i;
    Set_End_Index( j, btop_j+1, bonds );

    bo_ij = &( ibond->bo_data );
    bo_ji = &( jbond->bo_data );
    bo_ji->BO = bo_ij->BO = BO;
    bo_ji->BO_s = bo_ij->BO_s = BO_s;
    bo_ji->BO_pi = bo_ij->BO_pi = BO_pi;
    bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2;

    /* Bond Order page2-3, derivative of total bond order prime */
    Cln_BOp_s = twbp->p_bo2 * C12 / r2;
    Cln_BOp_pi = twbp->p_bo4 * C34 / r2;
    Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2;

    /* Only dln_BOp_xx wrt. dr_i is stored here, note that
       dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */
    rvec_Scale(bo_ij->dln_BOp_s,-bo_ij->BO_s*Cln_BOp_s,ibond->dvec);
    rvec_Scale(bo_ij->dln_BOp_pi,-bo_ij->BO_pi*Cln_BOp_pi,ibond->dvec);
    rvec_Scale(bo_ij->dln_BOp_pi2,
               -bo_ij->BO_pi2*Cln_BOp_pi2,ibond->dvec);
    rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s);
    rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi );
    rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2 );

    rvec_Scale( bo_ij->dBOp,
                -(bo_ij->BO_s * Cln_BOp_s +
                  bo_ij->BO_pi * Cln_BOp_pi +
                  bo_ij->BO_pi2 * Cln_BOp_pi2), ibond->dvec );
    rvec_Scale( bo_ji->dBOp, -1., bo_ij->dBOp );

    rvec_Add( workspace->dDeltap_self[i], bo_ij->dBOp );
    rvec_Add( workspace->dDeltap_self[j], bo_ji->dBOp );

    bo_ij->BO_s -= bo_cut;
    bo_ij->BO -= bo_cut;
    bo_ji->BO_s -= bo_cut;
    bo_ji->BO -= bo_cut;
    workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp
    workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp
    bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0;
    bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0;

    return 1;
  }

  return 0;
}