コード例 #1
0
/************************ 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;
}
コード例 #2
0
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] );
    }
  }
}
コード例 #3
0
void Compute_Kinetic_Energy( reax_system* system, simulation_data* data,
                             MPI_Comm comm )
{
  int i;
  rvec p;
  double 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;
}
コード例 #4
0
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
}
コード例 #5
0
ファイル: forces.c プロジェクト: zhang-b/PuReMD
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
}
コード例 #6
0
ファイル: forces.c プロジェクト: zhang-b/PuReMD
void Compute_Bond_Boost_Force_All_Couple(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists, 
        output_controls *out_control) {
  int i, j, pj;
  int type_i, type_j;
  int adatom, adatom2; // label the boost atom
  int nbond, nrad; // Nb
  int start_i, end_i;
  real e, emax, r, re, r_max; // eta, eta_max, r, r_e
  real bo;
  real A, dA, V; // A(\eta^max), and \Delta A(\eta^max)
  real *rv, *rv_max;
  real q, P1, vmax; // q, P1 in equation 13
  real S1, S2, f1, f2, C1, C2;
  real T;
  real bf, bfactor; // boost force scale
  rvec df; // boost force
  reax_atom *atom1, *atom2;
  bond_order_data *bo_ij;
  two_body_parameters *twbp;
  list *bonds;

  nrad = Find_Radicals(system, control, data, workspace, lists, out_control);
  //nrad = 0;
  //printf("-------------------------step %d  -----------------\n", data->step);
  bonds = (*lists) + BONDS;

  // bond boost parameters
  q = control->bboost_q; // should read this from control file
  P1 = control->bboost_P1; 
  vmax = control->bboost_Vmax;

  // initiate parameters
  e = 0;
  adatom = 0;
  adatom2 = 0;
  bo = 0.0;
  re = 0.001;

  A = 0.0;
  dA = 0.0;
  r_max = 0.0;
  bfactor = 1.0;
  T = control->T_final;
  V = 0.0; // bost energy
  nbond = 0;
  emax = 0.0;

  // first get the max bond order
  for( i=0; i < system->N; ++i ) {
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);
    for( pj = start_i; pj < end_i; ++pj ){
      if( i < bonds->select.bond_list[pj].nbr ) {
        j = bonds->select.bond_list[pj].nbr;
        type_i = system->atoms[i].type;
        type_j = system->atoms[j].type;
        twbp = &( system->reaxprm.tbp[type_i][type_j] );
        vmax = control->bboost_Vmax;
        vmax = twbp->v_max;
        bo_ij = &( bonds->select.bond_list[pj].bo_data );
        re = twbp->r_e; // get r_e from ffield.ext
        r = bonds->select.bond_list[pj].d;
        e = (r - re)/re; // eta
        bo = bo_ij->BO;
        if (bo > q && vmax > 0) {
            nbond += 1;
            if ( fabs(emax) < fabs(e) ) {
                emax = e;
                adatom = i;
                adatom2 = j;
                /* for debug
                printf("i = %d, j = %d, re = %.2f, r = %.2f ", i, j, re, r);
                printf("x1 = %.2f, y1 = %.2f, z1 = %.2f, ", \
                system->atoms[i].x[0], system->atoms[i].x[1], system->atoms[i].x[2]);
                printf("x2 = %.2f, y2 = %.2f, z2 = %.2f\n", \
                system->atoms[j].x[0], system->atoms[j].x[1], system->atoms[j].x[2]);
                printf( " %4s %4s\n", \
                system->reaxprm.sbp[ system->atoms[i].type ].name, 
                system->reaxprm.sbp[ system->atoms[j].type ].name);
                */
                rv_max = bonds->select.bond_list[pj].dvec;
                r_max = bonds->select.bond_list[pj].d;;
            }
        }
      }
    }
  }

  int ntmp; 
  if (fabs(emax) < q && nbond > 0 && nrad <= control->bboost_nrad) {
    data->boost ++ ;
    // calculate A, and dA
    S1 = emax/q;
    S2 = S1 * S1;
    C1 = 1 - (emax/q)*(emax/q);
    C2 = 1 - P1*P1*S2;
    A = C1 * C1 / C2;

    ntmp = 0;
    for( i=0; i < system->N; ++i ) {
      start_i = Start_Index(i, bonds);
      end_i = End_Index(i, bonds);
      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
          j = bonds->select.bond_list[pj].nbr;
          type_i = system->atoms[i].type;
          type_j = system->atoms[j].type;
          twbp = &( system->reaxprm.tbp[type_i][type_j] );
          vmax = control->bboost_Vmax;
          vmax = twbp->v_max;
          bo_ij = &( bonds->select.bond_list[pj].bo_data );
          r = bonds->select.bond_list[pj].d;
          re = twbp->r_e; // get r_e from ffield.ext
          rv = bonds->select.bond_list[pj].dvec;
          bo = bo_ij->BO;
          if (bo > q && vmax > 0) {

            e = (r - re)/re; // eta
            C1 = 1 - e*e/(q*q);
            V += vmax / nbond * C1;
            bf = 2*A*vmax*e/(nbond*q*q*re);

            if (fabs(e - emax) < 0.00001) {
                C2 = 1 - e*e*P1*P1/(q*q);
                f1 = 2/(q*q*re);
                f2 = f1/2*P1*P1;
                dA = 2*e*C1/C2*(f1 - f2*C1/C2);
            }
            rvec_Scale(df, bf, rv);
            atom1 = &( system->atoms[i] );
            atom2 = &( system->atoms[j] );
            rvec_Add(system->atoms[i].f, df);
            rvec_ScaledAdd(system->atoms[j].f, -1, df);
            ntmp++;
          }
        }
      }
    }
    // add the contribution of evalope function A
    bf = dA * V;
    rvec_Scale(df, bf, rv_max);
    atom1 = &( system->atoms[adatom]);
    rvec_Add(system->atoms[adatom].f, df);
    rvec_ScaledAdd(system->atoms[adatom2].f, -1, df);
  }
  else {
    data->boost = 0;
  }
  bfactor = exp(4184 * A * V/(T * 8.314));
  //bfactor = V;
  fprintf( out_control->bboost, "%-10d%6d%6d%6d%3d%8.4f%8.4f %44.4f", \
  data->step, nbond, adatom, adatom2, nrad, r_max, emax, bfactor );

  fprintf( out_control->bboost, " %4s %4s\n", \
  system->reaxprm.sbp[ system->atoms[adatom].type ].name, 
  system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  fflush( out_control->bboost);
}
コード例 #7
0
ファイル: forces.c プロジェクト: zhang-b/PuReMD
void Compute_Bond_Boost_Force(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists, 
        output_controls *out_control) {
  int i, j, pj;
  int type_i, type_j;
  int adatom, adatom2; // label the boost atom
  int nbond, nrad; // Nb
  int start_i, end_i;
  real e, emax, r, re, r_max; // eta, eta_max, r, r_e
  real bo;
  real A, dA, V; // A(\eta^max), and \Delta A(\eta^max)
  real *rv, *rv_max;
  real q, P1, vmax; // q, P1 in equation 13
  real S1, S2, f1, f2, C1, C2;
  real bf; // boost force scale
  rvec df; // boost force
  reax_atom *atom1, *atom2;
  bond_order_data *bo_ij;
  two_body_parameters *twbp;
  list *bonds;

  nrad = Find_Radicals(system, control, data, workspace, lists, out_control);
  //printf("-------------------------step %d  -----------------\n", data->step);
  bonds = (*lists) + BONDS;

  // bond boost parameters
  q = control->bboost_q; // should read this from control file
  P1 = control->bboost_P1; 
  vmax = control->bboost_Vmax;

  // initiate parameters
  e = 0;
  adatom = 0;
  adatom2 = 0;
  nbond = 0;
  emax = 0.0;
  bo = 0.0;
  re = 0.001;

  A = 0.0;
  dA = 0.0;
  r_max = 0.0;

  // first get the max bond order
  for( i=0; i < system->N; ++i ) {
    re = 0.001;
    start_i = Start_Index(i, bonds);
    end_i = End_Index(i, bonds);
    for( pj = start_i; pj < end_i; ++pj ){
      if( i < bonds->select.bond_list[pj].nbr ) {
        j = bonds->select.bond_list[pj].nbr;
        type_i = system->atoms[i].type;
        type_j = system->atoms[j].type;
        twbp = &( system->reaxprm.tbp[type_i][type_j] );
        bo_ij = &( bonds->select.bond_list[pj].bo_data );
        re = twbp->r_e; // get r_e from ffield.ext
        r = bonds->select.bond_list[pj].d;
        e = (r - re)/re; // eta
        //printf("r = %f, re = %f, e = %f\n", r, re, e);
        bo = bo_ij->BO;
        if ( (fabs (emax) < fabs(e)) & (bo > q)) {
            emax = e;
            adatom = i;
            adatom2 = j;
        }
      }
    }
  }
  /*
  printf("atom1 = %s ", system->reaxprm.sbp[ system->atoms[adatom].type ].name);
  printf("atom2 = %s ", system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  printf("bo = %f\n", bo);
  */

  V = 0.0; // boost energy

  if (fabs(emax) < q && nrad == 0) {
      i = adatom;
      vmax = control->bboost_Vmax;

      // calculate A, and dA
      S1 = emax/q;
      S2 = S1 * S1;
      C1 = 1 - (emax/q)*(emax/q);
      C2 = 1 - P1*P1*S2;
      A = C1 * C1 / C2;

      /*
      printf("S1 = %f, S2 = %f ", S1, S2);
      printf("C1 = %f, C2 = %f ", C1, C2);
      printf("A = %f, emax = %f\n", A, emax);
      */

      start_i = Start_Index(i, bonds);
      end_i = End_Index(i, bonds);
      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
            bo_ij = &( bonds->select.bond_list[pj].bo_data );
            bo = bo_ij->BO;
            if (bo > 0.3)
                nbond += 1;
        }
      }

      for( pj = start_i; pj < end_i; ++pj ) {
        if( i < bonds->select.bond_list[pj].nbr ) {
          bo_ij = &( bonds->select.bond_list[pj].bo_data );
          bo = bo_ij->BO;
          if (bo > 0.3) {
            j = bonds->select.bond_list[pj].nbr;
            r = bonds->select.bond_list[pj].d;
            rv = bonds->select.bond_list[pj].dvec;
            type_i = system->atoms[i].type;
            type_j = system->atoms[j].type;
            twbp = &( system->reaxprm.tbp[type_i][type_j] );
            vmax = twbp->v_max;
            re = twbp->r_e; // get r_e from ffield.ext

            e = (r - re)/re; // eta
            C1 = 1 - e*e/(q*q);
            V += vmax / nbond * C1;
            bf = 2*A*vmax*e/(nbond*q*re);

            /*
            printf("e = %.3f, emax = %.3f, C1 = %.3f, re = %.3f, V = %.3f, A = %.3f bf = %.3f, vmax = %.3f, \n",\
                    e, emax, C1, re, V, A, bf, vmax);
            */

            if (fabs(e - emax) < 0.00001) {
                C2 = 1 - e*e*P1*P1/(q*q);
                f1 = 2/(q*re);
                f2 = f1/2*P1*P1;
                dA = 2*e*C1/C2*(f1 - f2*C1/C2);
                rv_max = bonds->select.bond_list[pj].dvec;
                r_max = bonds->select.bond_list[pj].d;;
            }
            rvec_Scale(df, bf, rv);
            //rvec_Scale(df, 1/r, df);
            // assign the boost force
            atom1 = &( system->atoms[i] );
            atom2 = &( system->atoms[j] );
            /* printf("ofx = %8.3f ofy = %8.3f ofz = %8.3f \n", system->atoms[i].f[0],\
                    system->atoms[i].f[1], system->atoms[i].f[2]);
            */
            rvec_Add(system->atoms[i].f, df);
            //printf(" fx = %8.3f  fy = %8.3f  fz = %8.3f \n", df[0], df[1], df[2]);
            /*
            rvec_Scale(df, -1, df);
            rvec_Add(system->atoms[j].f, df);
            */
          }
        }
      }
      // add the contribution of evalope function A
      bf = dA * V;
      rvec_Scale(df, bf, rv_max);
      //rvec_Scale(df, 1/r_max, df);
      //printf("Max bf = %8.3f\n", bf);
      /*
      printf("Mfx = %8.3f Mfy = %8.3f Mfz = %8.3f dA = %8.3f V = %8.3f emax = %8.3f \n",\
             df[0], df[1], df[2], dA, V, emax);
      */
      atom1 = &( system->atoms[i] );
      rvec_Add(system->atoms[i].f, df);
  }

  fprintf( out_control->bboost, "%-10d%6d%6d%10.4f%10.4f%10.4f", \
  data->step, adatom + 1, adatom2 + 1, bo, emax, A*V );

  fprintf( out_control->bboost, " %4s %4s\n", \
  system->reaxprm.sbp[ system->atoms[adatom].type ].name, 
  system->reaxprm.sbp[ system->atoms[adatom2].type ].name);
  fflush( out_control->bboost);
}
コード例 #8
0
ファイル: forces.c プロジェクト: zhang-b/PuReMD
void Compute_AMD_Force(reax_system *system, control_params *control,
		simulation_data *data, static_storage *workspace, list **lists) {
	/**
	 * compute the AMD energy and force.
	 */
	int i, type_i;
	real q;
	real E_Pol, E_Pot;
	real delta_Pot, fscale;
	real s1, s2, s3, s4;
    // initiate parameters
    delta_Pot = 0.0;
    fscale = 0.0;
	/* Compute Potential Energy */
	E_Pol = 0.0;
	for (i = 0; i < system->N; i++) {
		q = system->atoms[i].q;
		type_i = system->atoms[i].type;

		E_Pol += (system->reaxprm.sbp[type_i].chi * q
				+ (system->reaxprm.sbp[type_i].eta / 2.0) * SQR(q))
				* KCALpMOL_to_EV;
	}

	E_Pot = data->E_BE + data->E_Ov + data->E_Un + data->E_Lp + data->E_Ang
			+ data->E_Pen + data->E_Coa + data->E_HB + data->E_Tor
			+ data->E_Con + data->E_vdW + data->E_Ele + data->E_Pol;
	/* compute delta V and Force scaling factor
	 * reference: JCTC 2011, 7, 890–897
	 */
	data->E_amd = control->amd_energy - data->Fragment_wat*120.0;
	if (data->E_amd > E_Pot) {
		if (control->amd_func == 1){
		/* s1 = Eb -V(r) */
		s1 = data->E_amd - E_Pot;
		/* s2 = (Eb -V(r))^p + a */
		s2 = POW(s1, control->amd_power) + control->amd_alpha;
		s3 = s1/s2/s2;
		s4 = control->amd_power*POW(s1, control->amd_power)-2*s2;
		delta_Pot = s1 * s1 / s2;
		fscale = 1 + s3*s4;
		}
		else if (control->amd_func == 2){
			s1 = data->E_amd - E_Pot;
			s2 = s1*s1;
			s3 = s2 + 2*s1;
			s4 = control->amd_alpha*(s3+1);
			delta_Pot = s2*(s1+1)/s4;
			fscale = 1-(s2+2*s1)/s4;
		}

		data->E_amd_delta = delta_Pot;
		data->F_amd_scale = fscale;
		/* scale the force */
		for (i = 0; i < system->N; ++i)
			rvec_Scale(system->atoms[i].f, fscale, system->atoms[i].f);
	}
	else
	{
		data->E_amd_delta = 0;
		data->F_amd_scale = 1;
	}
	//printf("in AMD no of water is %12.4f\n", data->F_amd_scale);
	//printf("in AMD no of water is %d\n", data->Fragment_wat);
}
コード例 #9
0
void Add_dBond_to_Forces( reax_system *system, int i, int pj,
                          storage *workspace, reax_list **lists )
{
  reax_list *bonds = (*lists) + BONDS;
  bond_data *nbr_j, *nbr_k;
  bond_order_data *bo_ij, *bo_ji;
  dbond_coefficients coef;
  int pk, k, j;

  /* Virial Tallying variables */
  rvec fi_tmp, fj_tmp, fk_tmp, delij, delji, delki, delkj, temp;

  /* Initializations */
  nbr_j = &(bonds->select.bond_list[pj]);
  j = nbr_j->nbr;
  bo_ij = &(nbr_j->bo_data);
  bo_ji = &(bonds->select.bond_list[ nbr_j->sym_index ].bo_data);

  coef.C1dbo = bo_ij->C1dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C2dbo = bo_ij->C2dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C3dbo = bo_ij->C3dbo * (bo_ij->Cdbo + bo_ji->Cdbo);

  coef.C1dbopi = bo_ij->C1dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C2dbopi = bo_ij->C2dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C3dbopi = bo_ij->C3dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C4dbopi = bo_ij->C4dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);

  coef.C1dbopi2 = bo_ij->C1dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C2dbopi2 = bo_ij->C2dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C3dbopi2 = bo_ij->C3dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C4dbopi2 = bo_ij->C4dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);

  coef.C1dDelta = bo_ij->C1dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C2dDelta = bo_ij->C2dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C3dDelta = bo_ij->C3dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);

  // forces on i
  rvec_Scale(           temp, coef.C1dbo,    bo_ij->dBOp );
  rvec_ScaledAdd( temp, coef.C2dbo,    workspace->dDeltap_self[i] );
  rvec_ScaledAdd( temp, coef.C1dDelta, bo_ij->dBOp );
  rvec_ScaledAdd( temp, coef.C2dDelta, workspace->dDeltap_self[i] );
  rvec_ScaledAdd( temp, coef.C1dbopi,  bo_ij->dln_BOp_pi );
  rvec_ScaledAdd( temp, coef.C2dbopi,  bo_ij->dBOp );
  rvec_ScaledAdd( temp, coef.C3dbopi,  workspace->dDeltap_self[i]);
  rvec_ScaledAdd( temp, coef.C1dbopi2, bo_ij->dln_BOp_pi2 );
  rvec_ScaledAdd( temp, coef.C2dbopi2, bo_ij->dBOp );
  rvec_ScaledAdd( temp, coef.C3dbopi2, workspace->dDeltap_self[i] );
  rvec_Add( workspace->f[i], temp );

  if( system->pair_ptr->vflag_atom) {
    rvec_Scale(fi_tmp, -1.0, temp);
    rvec_ScaledSum( delij, 1., system->my_atoms[i].x,-1., system->my_atoms[j].x );
    system->pair_ptr->v_tally(i,fi_tmp,delij);
  }

  // forces on j
  rvec_Scale(           temp, -coef.C1dbo,    bo_ij->dBOp );
  rvec_ScaledAdd( temp,  coef.C3dbo,    workspace->dDeltap_self[j] );
  rvec_ScaledAdd( temp, -coef.C1dDelta, bo_ij->dBOp );
  rvec_ScaledAdd( temp,  coef.C3dDelta, workspace->dDeltap_self[j]);
  rvec_ScaledAdd( temp, -coef.C1dbopi,  bo_ij->dln_BOp_pi );
  rvec_ScaledAdd( temp, -coef.C2dbopi,  bo_ij->dBOp );
  rvec_ScaledAdd( temp,  coef.C4dbopi,  workspace->dDeltap_self[j]);
  rvec_ScaledAdd( temp, -coef.C1dbopi2, bo_ij->dln_BOp_pi2 );
  rvec_ScaledAdd( temp, -coef.C2dbopi2, bo_ij->dBOp );
  rvec_ScaledAdd( temp,  coef.C4dbopi2, workspace->dDeltap_self[j]);
  rvec_Add( workspace->f[j], temp );

  if( system->pair_ptr->vflag_atom) {
    rvec_Scale(fj_tmp, -1.0, temp);
    rvec_ScaledSum( delji, 1., system->my_atoms[j].x,-1., system->my_atoms[i].x );
    system->pair_ptr->v_tally(j,fj_tmp,delji);
  }

  // forces on k: i neighbor
  for( pk = Start_Index(i, bonds); pk < End_Index(i, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale(     temp, -coef.C2dbo,    nbr_k->bo_data.dBOp);
    rvec_ScaledAdd( temp, -coef.C2dDelta, nbr_k->bo_data.dBOp);
    rvec_ScaledAdd( temp, -coef.C3dbopi,  nbr_k->bo_data.dBOp);
    rvec_ScaledAdd( temp, -coef.C3dbopi2, nbr_k->bo_data.dBOp);
    rvec_Add( workspace->f[k], temp );

    if( system->pair_ptr->vflag_atom ) {
      rvec_Scale(fk_tmp, -1.0, temp);
      rvec_ScaledSum(delki,1.,system->my_atoms[k].x,-1.,system->my_atoms[i].x);
      system->pair_ptr->v_tally(k,fk_tmp,delki);
      rvec_ScaledSum(delkj,1.,system->my_atoms[k].x,-1.,system->my_atoms[j].x);
      system->pair_ptr->v_tally(k,fk_tmp,delkj);
    }
  }

  // forces on k: j neighbor
  for( pk = Start_Index(j, bonds); pk < End_Index(j, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale(     temp, -coef.C3dbo,    nbr_k->bo_data.dBOp );
    rvec_ScaledAdd( temp, -coef.C3dDelta, nbr_k->bo_data.dBOp);
    rvec_ScaledAdd( temp, -coef.C4dbopi,  nbr_k->bo_data.dBOp);
    rvec_ScaledAdd( temp, -coef.C4dbopi2, nbr_k->bo_data.dBOp);
    rvec_Add( workspace->f[k], temp );

    if( system->pair_ptr->vflag_atom ) {
      rvec_Scale(fk_tmp, -1.0, temp);
      rvec_ScaledSum(delki,1.,system->my_atoms[k].x,-1.,system->my_atoms[i].x);
      system->pair_ptr->v_tally(k,fk_tmp,delki);
      rvec_ScaledSum(delkj,1.,system->my_atoms[k].x,-1.,system->my_atoms[j].x);
      system->pair_ptr->v_tally(k,fk_tmp,delkj);
    }
  }

}
コード例 #10
0
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 );
}
コード例 #11
0
void Compute_Center_of_Mass( reax_system *system, simulation_data *data,
                             mpi_datatypes *mpi_data, MPI_Comm comm )
{
  int i;
  double m, det; //xx, xy, xz, yy, yz, zz;
  double 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 );

}
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;

  double temp, temp_bo_jt, pBOjt7;
  double p_val1, p_val2, p_val3, p_val4, p_val5;
  double p_val6, p_val7, p_val8, p_val9, p_val10;
  double p_pen1, p_pen2, p_pen3, p_pen4;
  double p_coa1, p_coa2, p_coa3, p_coa4;
  double trm8, expval6, expval7, expval2theta, expval12theta, exp3ij, exp3jk;
  double exp_pen2ij, exp_pen2jk, exp_pen3, exp_pen4, trm_pen34, exp_coa2;
  double dSBO1, dSBO2, SBO, SBO2, CSBO2, SBOp, prod_SBO, vlpadj;
  double CEval1, CEval2, CEval3, CEval4, CEval5, CEval6, CEval7, CEval8;
  double CEpen1, CEpen2, CEpen3;
  double e_ang, e_coa, e_pen;
  double CEcoa1, CEcoa2, CEcoa3, CEcoa4, CEcoa5;
  double Cf7ij, Cf7jk, Cf8j, Cf9j;
  double f7_ij, f7_jk, f8_Dj, f9_Dj;
  double Ctheta_0, theta_0, theta_00, theta, cos_theta, sin_theta;
  double BOA_ij, BOA_jk;
  rvec force, ext_press;

  // Tallying variables
  double eng_tmp, fi_tmp[3], fj_tmp[3], fk_tmp[3];
  double delij[3], delkj[3];

  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 ) {         // Ray: the first one with system->N
    type_j = system->my_atoms[j].type;
    if (type_j < 0) continue;
    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 );
    }

    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;
        type_i = system->my_atoms[i].type;

        for( pk = start_j; pk < pi; ++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;
            }
        }

        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 > control->thb_cut) &&
              (bo_jk->BO > control->thb_cut) &&
              (bo_ij->BO * bo_jk->BO > control->thb_cutsq) ) {
            thbh = &( system->reax_param.thbp[ type_i ][ type_j ][ type_k ] );

            for( cnt = 0; cnt < thbh->cnt; ++cnt ) {
              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_val[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;

                    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 {
                  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 );
                }

                /* tally into per-atom virials */
                if( system->pair_ptr->vflag_atom || system->pair_ptr->evflag) {

                  /* Acquire vectors */
                  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, -CEval8, p_ijk->dcos_di );
                  rvec_Scale( fj_tmp, -CEval8, p_ijk->dcos_dj );
                  rvec_Scale( fk_tmp, -CEval8, p_ijk->dcos_dk );

                  eng_tmp = e_ang + e_pen + e_coa;

                  if( system->pair_ptr->evflag)
                          system->pair_ptr->ev_tally(j,j,system->N,1,eng_tmp,0.0,0.0,0.0,0.0,0.0);
                  if( system->pair_ptr->vflag_atom)
                          system->pair_ptr->v_tally3(i,j,k,fi_tmp,fk_tmp,delij,delkj);
                }
              }
            }
          }
        }
      }

      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 );
    }
  }

}
コード例 #13
0
void Add_dBond_to_Forces_NPT( int i, int pj, simulation_data *data,
                              storage *workspace, reax_list **lists )
{
  reax_list *bonds = (*lists) + BONDS;
  bond_data *nbr_j, *nbr_k;
  bond_order_data *bo_ij, *bo_ji;
  dbond_coefficients coef;
  rvec temp, ext_press;
  ivec rel_box;
  int pk, k, j;

  /* Initializations */
  nbr_j = &(bonds->select.bond_list[pj]);
  j = nbr_j->nbr;
  bo_ij = &(nbr_j->bo_data);
  bo_ji = &(bonds->select.bond_list[ nbr_j->sym_index ].bo_data);

  coef.C1dbo = bo_ij->C1dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C2dbo = bo_ij->C2dbo * (bo_ij->Cdbo + bo_ji->Cdbo);
  coef.C3dbo = bo_ij->C3dbo * (bo_ij->Cdbo + bo_ji->Cdbo);

  coef.C1dbopi = bo_ij->C1dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C2dbopi = bo_ij->C2dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C3dbopi = bo_ij->C3dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);
  coef.C4dbopi = bo_ij->C4dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi);

  coef.C1dbopi2 = bo_ij->C1dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C2dbopi2 = bo_ij->C2dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C3dbopi2 = bo_ij->C3dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);
  coef.C4dbopi2 = bo_ij->C4dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2);

  coef.C1dDelta = bo_ij->C1dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C2dDelta = bo_ij->C2dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);
  coef.C3dDelta = bo_ij->C3dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]);

  for( pk = Start_Index(i, bonds); pk < End_Index(i, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale(temp, -coef.C2dbo, nbr_k->bo_data.dBOp);       /*2nd, dBO*/
    rvec_ScaledAdd(temp, -coef.C2dDelta, nbr_k->bo_data.dBOp);/*dDelta*/
    rvec_ScaledAdd(temp, -coef.C3dbopi, nbr_k->bo_data.dBOp); /*3rd, dBOpi*/
    rvec_ScaledAdd(temp, -coef.C3dbopi2, nbr_k->bo_data.dBOp);/*3rd, dBOpi2*/

    /* force */
    rvec_Add( workspace->f[k], temp );
    /* pressure */
    rvec_iMultiply( ext_press, nbr_k->rel_box, temp );
    rvec_Add( data->my_ext_press, ext_press );

  }

  /* then atom i itself  */
  rvec_Scale( temp, coef.C1dbo, bo_ij->dBOp );                      /*1st,dBO*/
  rvec_ScaledAdd( temp, coef.C2dbo, workspace->dDeltap_self[i] );   /*2nd,dBO*/
  rvec_ScaledAdd( temp, coef.C1dDelta, bo_ij->dBOp );               /*1st,dBO*/
  rvec_ScaledAdd( temp, coef.C2dDelta, workspace->dDeltap_self[i] );/*2nd,dBO*/
  rvec_ScaledAdd( temp, coef.C1dbopi, bo_ij->dln_BOp_pi );        /*1st,dBOpi*/
  rvec_ScaledAdd( temp, coef.C2dbopi, bo_ij->dBOp );              /*2nd,dBOpi*/
  rvec_ScaledAdd( temp, coef.C3dbopi, workspace->dDeltap_self[i]);/*3rd,dBOpi*/

  rvec_ScaledAdd( temp, coef.C1dbopi2, bo_ij->dln_BOp_pi2 );  /*1st,dBO_pi2*/
  rvec_ScaledAdd( temp, coef.C2dbopi2, bo_ij->dBOp );         /*2nd,dBO_pi2*/
  rvec_ScaledAdd( temp, coef.C3dbopi2, workspace->dDeltap_self[i] );/*3rd*/

  /* force */
  rvec_Add( workspace->f[i], temp );

  for( pk = Start_Index(j, bonds); pk < End_Index(j, bonds); ++pk ) {
    nbr_k = &(bonds->select.bond_list[pk]);
    k = nbr_k->nbr;

    rvec_Scale( temp, -coef.C3dbo, nbr_k->bo_data.dBOp );      /*3rd,dBO*/
    rvec_ScaledAdd( temp, -coef.C3dDelta, nbr_k->bo_data.dBOp);/*dDelta*/
    rvec_ScaledAdd( temp, -coef.C4dbopi, nbr_k->bo_data.dBOp); /*4th,dBOpi*/
    rvec_ScaledAdd( temp, -coef.C4dbopi2, nbr_k->bo_data.dBOp);/*4th,dBOpi2*/

    /* force */
    rvec_Add( workspace->f[k], temp );
    /* pressure */
    if( k != i ) {
      ivec_Sum( rel_box, nbr_k->rel_box, nbr_j->rel_box ); //rel_box(k, i)
      rvec_iMultiply( ext_press, rel_box, temp );
      rvec_Add( data->my_ext_press, ext_press );

    }
  }

  /* then atom j itself */
  rvec_Scale( temp, -coef.C1dbo, bo_ij->dBOp );                    /*1st, dBO*/
  rvec_ScaledAdd( temp, coef.C3dbo, workspace->dDeltap_self[j] );  /*2nd, dBO*/
  rvec_ScaledAdd( temp, -coef.C1dDelta, bo_ij->dBOp );             /*1st, dBO*/
  rvec_ScaledAdd( temp, coef.C3dDelta, workspace->dDeltap_self[j]);/*2nd, dBO*/

  rvec_ScaledAdd( temp, -coef.C1dbopi, bo_ij->dln_BOp_pi );       /*1st,dBOpi*/
  rvec_ScaledAdd( temp, -coef.C2dbopi, bo_ij->dBOp );             /*2nd,dBOpi*/
  rvec_ScaledAdd( temp, coef.C4dbopi, workspace->dDeltap_self[j]);/*3rd,dBOpi*/

  rvec_ScaledAdd( temp, -coef.C1dbopi2, bo_ij->dln_BOp_pi2 );    /*1st,dBOpi2*/
  rvec_ScaledAdd( temp, -coef.C2dbopi2, bo_ij->dBOp );           /*2nd,dBOpi2*/
  rvec_ScaledAdd( temp,coef.C4dbopi2,workspace->dDeltap_self[j]);/*3rd,dBOpi2*/

  /* force */
  rvec_Add( workspace->f[j], temp );
  /* pressure */
  rvec_iMultiply( ext_press, nbr_j->rel_box, temp );
  rvec_Add( data->my_ext_press, ext_press );

}
コード例 #14
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;
}
コード例 #15
0
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;
  int type_i, type_j, tmin, tmax;
  int start_i, end_i, flag;
  rc_tagint orig_i, orig_j;
  double r_ij, base, dif;
  double e_vdW, e_ele;
  double CEvd, CEclmb, SMALL = 0.0001;
  double f_tmp, delij[3];

  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;

  e_ele = e_vdW = 0;

  for( i = 0; i < natoms; ++i ) {
    type_i  = system->my_atoms[i].type;
    if (type_i < 0) continue;
    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;
      type_j = system->my_atoms[j].type;
      if (type_j < 0) continue;
      orig_j  = system->my_atoms[j].orig_id;

      flag = 0;
      if(nbr_pj->d <= control->nonb_cut) {
        if (j < natoms) flag = 1;
        else if (orig_i < orig_j) flag = 1;
        else if (orig_i == orig_j) {
          if (nbr_pj->dvec[2] > SMALL) flag = 1;
          else if (fabs(nbr_pj->dvec[2]) < SMALL) {
            if (nbr_pj->dvec[1] > SMALL) flag = 1;
            else if (fabs(nbr_pj->dvec[1]) < SMALL && nbr_pj->dvec[0] > SMALL)
              flag = 1;
          }
        }
      }

      if (flag) {

      r_ij   = nbr_pj->d;
      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 = (double)(r+1) * t->dx;
      dif = r_ij - base;

      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;

      /* tally into per-atom energy */
      if( system->pair_ptr->evflag || system->pair_ptr->vflag_atom) {
        rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                              -1., system->my_atoms[j].x );
        f_tmp = -(CEvd + CEclmb);
        system->pair_ptr->ev_tally(i,j,natoms,1,e_vdW,e_ele,
                        f_tmp,delij[0],delij[1],delij[2]);
      }

      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
        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 );
      }
      }
    }
  }

  Compute_Polarization_Energy( system, data );
}
コード例 #16
0
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, flag;
  rc_tagint orig_i, orig_j;
  double p_vdW1, p_vdW1i;
  double powr_vdW1, powgi_vdW1;
  double tmp, r_ij, fn13, exp1, exp2;
  double Tap, dTap, dfn13, CEvd, CEclmb, de_core;
  double dr3gamij_1, dr3gamij_3;
  double e_ele, e_vdW, e_core, SMALL = 0.0001;
  double e_lg, de_lg, r_ij5, r_ij6, re6;
  rvec temp, ext_press;
  two_body_parameters *twbp;
  far_neighbor_data *nbr_pj;
  reax_list *far_nbrs;

  // Tallying variables:
  double pe_vdw, f_tmp, delij[3];

  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;
  e_lg = de_lg = 0.0;

  for( i = 0; i < natoms; ++i ) {
    if (system->my_atoms[i].type < 0) continue;
    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;
      if (system->my_atoms[j].type < 0) continue;
      orig_j  = system->my_atoms[j].orig_id;

      flag = 0;
      if(nbr_pj->d <= control->nonb_cut) {
        if (j < natoms) flag = 1;
        else if (orig_i < orig_j) flag = 1;
        else if (orig_i == orig_j) {
          if (nbr_pj->dvec[2] > SMALL) flag = 1;
          else if (fabs(nbr_pj->dvec[2]) < SMALL) {
            if (nbr_pj->dvec[1] > SMALL) flag = 1;
            else if (fabs(nbr_pj->dvec[1]) < SMALL && nbr_pj->dvec[0] > SMALL)
              flag = 1;
          }
        }
      }

      if (flag) {

      r_ij = nbr_pj->d;
      twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ]
                                       [ system->my_atoms[j].type ]);

      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) / r_ij;
      }

      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 / r_ij;

          //  lg correction, only if lgvdw is yes
          if (control->lgflag) {
            r_ij5 = pow( r_ij, 5.0 );
            r_ij6 = pow( r_ij, 6.0 );
            re6 = pow( twbp->lgre, 6.0 );
            e_lg = -(twbp->lgcij/( r_ij6 + re6 ));
            data->my_en.e_vdW += Tap * e_lg;

            de_lg = -6.0 * e_lg *  r_ij5 / ( r_ij6 + re6 ) ;
            CEvd += dTap * e_lg + Tap * de_lg / r_ij;
          }

        }

      /*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;

      /* tally into per-atom energy */
      if( system->pair_ptr->evflag || system->pair_ptr->vflag_atom) {
        pe_vdw = Tap * (e_vdW + e_core + e_lg);
        rvec_ScaledSum( delij, 1., system->my_atoms[i].x,
                              -1., system->my_atoms[j].x );
        f_tmp = -(CEvd + CEclmb);
        system->pair_ptr->ev_tally(i,j,natoms,1,pe_vdw,e_ele,
                        f_tmp,delij[0],delij[1],delij[2]);
      }

      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 */
        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 );
      }
      }
    }
  }

  Compute_Polarization_Energy( system, data );
}
コード例 #17
0
ファイル: forces.c プロジェクト: zhang-b/PuReMD
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
}
コード例 #18
0
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) / r_ij;
      }

      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 / r_ij;
	}

      /*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 );
}
コード例 #19
0
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_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;
  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;

  for( j = 0; j < system->n; ++j )
    if( system->reax_param.sbp[system->my_atoms[j].type].p_hbond == 1 ) {
      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 );
      if (type_j < 0) continue;

      top = 0;
      for( pi = start_j; pi < end_j; ++pi )  {
        pbond_ij = &( bond_list[pi] );
        i = pbond_ij->nbr;
        type_i = system->my_atoms[i].type;
	if (type_i < 0) continue;
        bo_ij = &(pbond_ij->bo_data);

        if( system->reax_param.sbp[type_i].p_hbond == 2 &&
            bo_ij->BO >= HB_THRESHOLD )
          hblist[top++] = pi;
      }

      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;
	if (type_k < 0) continue;
        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;
	    if (type_i < 0) continue;
            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;

            /* 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 {
              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[j].x,
                                    -1., system->my_atoms[i].x );
              rvec_ScaledSum( delkj, 1., system->my_atoms[j].x,
                                     -1., system->my_atoms[k].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);
            }
          }
        }
      }
    }
}